def10e8af7f6b577b09a451b4cf29ee6eda593d5
[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 LONG
90 ReadRegDwordKey(
91 IN HKEY hKey,
92 IN LPCWSTR pszKey,
93 OUT LPDWORD pValue)
94 {
95 LONG rc;
96 DWORD dwType;
97 DWORD cbData;
98 DWORD dwValue;
99
100 if (!pValue)
101 return ERROR_INVALID_PARAMETER;
102
103 cbData = sizeof(DWORD);
104 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, (LPBYTE)&dwValue, &cbData);
105 if (rc == ERROR_SUCCESS && dwType == REG_DWORD)
106 *pValue = dwValue;
107
108 return ERROR_SUCCESS;
109 }
110
111 static VOID
112 ChooseGinaUI(VOID)
113 {
114 HKEY ControlKey = NULL;
115 LPWSTR SystemStartOptions = NULL;
116 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
117 BOOL ConsoleBoot = FALSE;
118 LONG rc;
119
120 rc = RegOpenKeyExW(
121 HKEY_LOCAL_MACHINE,
122 L"SYSTEM\\CurrentControlSet\\Control",
123 0,
124 KEY_QUERY_VALUE,
125 &ControlKey);
126
127 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
128 if (rc != ERROR_SUCCESS)
129 goto cleanup;
130
131 /* Check for CONSOLE switch in SystemStartOptions */
132 CurrentOption = SystemStartOptions;
133 while (CurrentOption)
134 {
135 NextOption = wcschr(CurrentOption, L' ');
136 if (NextOption)
137 *NextOption = L'\0';
138 if (wcsicmp(CurrentOption, L"CONSOLE") == 0)
139 {
140 TRACE("Found %S. Switching to console boot\n", CurrentOption);
141 ConsoleBoot = TRUE;
142 goto cleanup;
143 }
144 CurrentOption = NextOption ? NextOption + 1 : NULL;
145 }
146
147 cleanup:
148 if (ConsoleBoot)
149 pGinaUI = &GinaTextUI;
150 else
151 pGinaUI = &GinaGraphicalUI;
152
153 if (ControlKey != NULL)
154 RegCloseKey(ControlKey);
155 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
156 }
157
158
159 static
160 BOOL
161 GetRegistrySettings(PGINA_CONTEXT pgContext)
162 {
163 HKEY hKey = NULL;
164 LPWSTR lpAutoAdminLogon = NULL;
165 DWORD dwDisableCAD = 0;
166 LONG rc;
167
168 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
169 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
170 0,
171 KEY_QUERY_VALUE,
172 &hKey);
173 if (rc != ERROR_SUCCESS)
174 {
175 WARN("RegOpenKeyExW() failed with error %lu\n", rc);
176 return FALSE;
177 }
178
179 rc = ReadRegSzKey(hKey,
180 L"AutoAdminLogon",
181 &lpAutoAdminLogon);
182 if (rc == ERROR_SUCCESS)
183 {
184 if (wcscmp(lpAutoAdminLogon, L"1") == 0)
185 pgContext->bAutoAdminLogon = TRUE;
186 }
187
188 TRACE("bAutoAdminLogon: %s\n", pgContext->bAutoAdminLogon ? "TRUE" : "FALSE");
189
190 rc = ReadRegDwordKey(hKey,
191 L"DisableCAD",
192 &dwDisableCAD);
193 if (rc == ERROR_SUCCESS)
194 {
195 if (dwDisableCAD != 0)
196 pgContext->bDisableCAD = TRUE;
197 }
198
199 TRACE("bDisableCAD: %s\n", pgContext->bDisableCAD ? "TRUE" : "FALSE");
200
201 if (lpAutoAdminLogon != NULL)
202 HeapFree(GetProcessHeap(), 0, lpAutoAdminLogon);
203
204 if (hKey != NULL)
205 RegCloseKey(hKey);
206
207 return TRUE;
208 }
209
210
211 /*
212 * @implemented
213 */
214 BOOL WINAPI
215 WlxInitialize(
216 LPWSTR lpWinsta,
217 HANDLE hWlx,
218 PVOID pvReserved,
219 PVOID pWinlogonFunctions,
220 PVOID *pWlxContext)
221 {
222 PGINA_CONTEXT pgContext;
223
224 UNREFERENCED_PARAMETER(pvReserved);
225
226 pgContext = (PGINA_CONTEXT)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(GINA_CONTEXT));
227 if(!pgContext)
228 {
229 WARN("LocalAlloc() failed\n");
230 return FALSE;
231 }
232
233 if (!GetRegistrySettings(pgContext))
234 {
235 WARN("GetRegistrySettings() failed\n");
236 LocalFree(pgContext);
237 return FALSE;
238 }
239
240 /* Return the context to winlogon */
241 *pWlxContext = (PVOID)pgContext;
242 pgContext->hDllInstance = hDllInstance;
243
244 /* Save pointer to dispatch table */
245 pgContext->pWlxFuncs = (PWLX_DISPATCH_VERSION_1_3)pWinlogonFunctions;
246
247 /* Save the winlogon handle used to call the dispatch functions */
248 pgContext->hWlx = hWlx;
249
250 /* Save window station */
251 pgContext->station = lpWinsta;
252
253 /* Clear status window handle */
254 pgContext->hStatusWindow = 0;
255
256 /* Notify winlogon that we will use the default SAS */
257 pgContext->pWlxFuncs->WlxUseCtrlAltDel(hWlx);
258
259 /* Locates the authentification package */
260 //LsaRegisterLogonProcess(...);
261
262 /* Check autologon settings the first time */
263 pgContext->AutoLogonState = AUTOLOGON_CHECK_REGISTRY;
264
265 ChooseGinaUI();
266 return pGinaUI->Initialize(pgContext);
267 }
268
269 /*
270 * @implemented
271 */
272 BOOL
273 WINAPI
274 WlxScreenSaverNotify(
275 PVOID pWlxContext,
276 BOOL *pSecure)
277 {
278 #if 0
279 WCHAR szBuffer[2];
280 HKEY hKey;
281 DWORD bufferSize = sizeof(szBuffer);
282 DWORD varType = REG_SZ;
283 LONG rc;
284
285 TRACE("(%p %p)\n", pWlxContext, pSecure);
286
287 *pSecure = TRUE;
288
289 /*
290 * Policy setting:
291 * HKLM\Software\Policies\Microsoft\Windows\Control Panel\Desktop : ScreenSaverIsSecure
292 * User setting:
293 * HKCU\Control Panel\Desktop : ScreenSaverIsSecure
294 */
295
296 rc = RegOpenKeyExW(HKEY_CURRENT_USER,
297 L"Control Panel\\Desktop",
298 0,
299 KEY_QUERY_VALUE,
300 &hKey);
301 TRACE("RegOpenKeyExW: %ld\n", rc);
302 if (rc == ERROR_SUCCESS)
303 {
304 rc = RegQueryValueExW(hKey,
305 L"ScreenSaverIsSecure",
306 NULL,
307 &varType,
308 (LPBYTE)szBuffer,
309 &bufferSize);
310
311 TRACE("RegQueryValueExW: %ld\n", rc);
312
313 if (rc == ERROR_SUCCESS)
314 {
315 TRACE("szBuffer: \"%S\"\n", szBuffer);
316 *pSecure = _wtoi(szBuffer);
317 }
318
319 RegCloseKey(hKey);
320 }
321
322 TRACE("*pSecure: %ld\n", *pSecure);
323 #endif
324
325 *pSecure = FALSE;
326
327 return TRUE;
328 }
329
330 /*
331 * @implemented
332 */
333 BOOL WINAPI
334 WlxStartApplication(
335 PVOID pWlxContext,
336 PWSTR pszDesktopName,
337 PVOID pEnvironment,
338 PWSTR pszCmdLine)
339 {
340 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
341 STARTUPINFOW StartupInfo;
342 PROCESS_INFORMATION ProcessInformation;
343 WCHAR CurrentDirectory[MAX_PATH];
344 HANDLE hAppToken;
345 UINT len;
346 BOOL ret;
347
348 len = GetWindowsDirectoryW(CurrentDirectory, MAX_PATH);
349 if (len == 0 || len > MAX_PATH)
350 {
351 ERR("GetWindowsDirectoryW() failed\n");
352 return FALSE;
353 }
354
355 ret = DuplicateTokenEx(pgContext->UserToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hAppToken);
356 if (!ret)
357 {
358 ERR("DuplicateTokenEx() failed with error %lu\n", GetLastError());
359 return FALSE;
360 }
361
362 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
363 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
364 StartupInfo.cb = sizeof(StartupInfo);
365 StartupInfo.lpTitle = pszCmdLine;
366 StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
367 StartupInfo.wShowWindow = SW_SHOW;
368 StartupInfo.lpDesktop = pszDesktopName;
369
370 len = GetWindowsDirectoryW(CurrentDirectory, MAX_PATH);
371 if (len == 0 || len > MAX_PATH)
372 {
373 ERR("GetWindowsDirectoryW() failed\n");
374 return FALSE;
375 }
376 ret = CreateProcessAsUserW(
377 hAppToken,
378 pszCmdLine,
379 NULL,
380 NULL,
381 NULL,
382 FALSE,
383 CREATE_UNICODE_ENVIRONMENT,
384 pEnvironment,
385 CurrentDirectory,
386 &StartupInfo,
387 &ProcessInformation);
388 CloseHandle(ProcessInformation.hProcess);
389 CloseHandle(ProcessInformation.hThread);
390 CloseHandle(hAppToken);
391 if (!ret)
392 ERR("CreateProcessAsUserW() failed with error %lu\n", GetLastError());
393 return ret;
394 }
395
396 /*
397 * @implemented
398 */
399 BOOL WINAPI
400 WlxActivateUserShell(
401 PVOID pWlxContext,
402 PWSTR pszDesktopName,
403 PWSTR pszMprLogonScript,
404 PVOID pEnvironment)
405 {
406 HKEY hKey;
407 DWORD BufSize, ValueType;
408 WCHAR pszUserInitApp[MAX_PATH + 1];
409 WCHAR pszExpUserInitApp[MAX_PATH];
410 DWORD len;
411 LONG rc;
412
413 TRACE("WlxActivateUserShell()\n");
414
415 UNREFERENCED_PARAMETER(pszMprLogonScript);
416
417 /* Get the path of userinit */
418 rc = RegOpenKeyExW(
419 HKEY_LOCAL_MACHINE,
420 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
421 0,
422 KEY_QUERY_VALUE,
423 &hKey);
424 if (rc != ERROR_SUCCESS)
425 {
426 WARN("RegOpenKeyExW() failed with error %lu\n", rc);
427 return FALSE;
428 }
429
430 /* Query userinit application */
431 BufSize = sizeof(pszUserInitApp) - sizeof(UNICODE_NULL);
432 rc = RegQueryValueExW(
433 hKey,
434 L"Userinit",
435 NULL,
436 &ValueType,
437 (LPBYTE)pszUserInitApp,
438 &BufSize);
439 RegCloseKey(hKey);
440 if (rc != ERROR_SUCCESS || (ValueType != REG_SZ && ValueType != REG_EXPAND_SZ))
441 {
442 WARN("RegQueryValueExW() failed with error %lu\n", rc);
443 return FALSE;
444 }
445 pszUserInitApp[MAX_PATH] = UNICODE_NULL;
446
447 len = ExpandEnvironmentStringsW(pszUserInitApp, pszExpUserInitApp, MAX_PATH);
448 if (len > MAX_PATH)
449 {
450 WARN("ExpandEnvironmentStringsW() failed. Required size %lu\n", len);
451 return FALSE;
452 }
453
454 /* Start userinit app */
455 return WlxStartApplication(pWlxContext, pszDesktopName, pEnvironment, pszExpUserInitApp);
456 }
457
458 /*
459 * @implemented
460 */
461 int WINAPI
462 WlxLoggedOnSAS(
463 PVOID pWlxContext,
464 DWORD dwSasType,
465 PVOID pReserved)
466 {
467 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
468 INT SasAction = WLX_SAS_ACTION_NONE;
469
470 TRACE("WlxLoggedOnSAS(0x%lx)\n", dwSasType);
471
472 UNREFERENCED_PARAMETER(pReserved);
473
474 switch (dwSasType)
475 {
476 case WLX_SAS_TYPE_CTRL_ALT_DEL:
477 case WLX_SAS_TYPE_TIMEOUT:
478 {
479 SasAction = pGinaUI->LoggedOnSAS(pgContext, dwSasType);
480 break;
481 }
482 case WLX_SAS_TYPE_SC_INSERT:
483 {
484 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_INSERT not supported!\n");
485 break;
486 }
487 case WLX_SAS_TYPE_SC_REMOVE:
488 {
489 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_REMOVE not supported!\n");
490 break;
491 }
492 default:
493 {
494 WARN("WlxLoggedOnSAS: Unknown SasType: 0x%x\n", dwSasType);
495 break;
496 }
497 }
498
499 return SasAction;
500 }
501
502 /*
503 * @implemented
504 */
505 BOOL WINAPI
506 WlxDisplayStatusMessage(
507 IN PVOID pWlxContext,
508 IN HDESK hDesktop,
509 IN DWORD dwOptions,
510 IN PWSTR pTitle,
511 IN PWSTR pMessage)
512 {
513 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
514
515 TRACE("WlxDisplayStatusMessage(\"%S\")\n", pMessage);
516
517 return pGinaUI->DisplayStatusMessage(pgContext, hDesktop, dwOptions, pTitle, pMessage);
518 }
519
520 /*
521 * @implemented
522 */
523 BOOL WINAPI
524 WlxRemoveStatusMessage(
525 IN PVOID pWlxContext)
526 {
527 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
528
529 TRACE("WlxRemoveStatusMessage()\n");
530
531 return pGinaUI->RemoveStatusMessage(pgContext);
532 }
533
534 static PWSTR
535 DuplicationString(PWSTR Str)
536 {
537 DWORD cb;
538 PWSTR NewStr;
539
540 if (Str == NULL) return NULL;
541
542 cb = (wcslen(Str) + 1) * sizeof(WCHAR);
543 if ((NewStr = LocalAlloc(LMEM_FIXED, cb)))
544 memcpy(NewStr, Str, cb);
545 return NewStr;
546 }
547
548 BOOL
549 DoLoginTasks(
550 IN OUT PGINA_CONTEXT pgContext,
551 IN PWSTR UserName,
552 IN PWSTR Domain,
553 IN PWSTR Password)
554 {
555 LPWSTR ProfilePath = NULL;
556 LPWSTR lpEnvironment = NULL;
557 TOKEN_STATISTICS Stats;
558 PWLX_PROFILE_V2_0 pProfile = NULL;
559 DWORD cbStats, cbSize;
560 DWORD dwLength;
561 BOOL bResult;
562
563 if (!LogonUserW(UserName, Domain, Password,
564 LOGON32_LOGON_INTERACTIVE,
565 LOGON32_PROVIDER_DEFAULT,
566 &pgContext->UserToken))
567 {
568 WARN("LogonUserW() failed\n");
569 goto cleanup;
570 }
571
572 /* Store the logon time in the context */
573 GetLocalTime(&pgContext->LogonTime);
574
575 /* Store user and domain in the context */
576 wcscpy(pgContext->UserName, UserName);
577 if (Domain == NULL || wcslen(Domain) == 0)
578 {
579 dwLength = 256;
580 GetComputerNameW(pgContext->Domain, &dwLength);
581 }
582 else
583 {
584 wcscpy(pgContext->Domain, Domain);
585 }
586
587 /* Get profile path */
588 cbSize = 0;
589 bResult = GetProfilesDirectoryW(NULL, &cbSize);
590 if (!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
591 {
592 ProfilePath = HeapAlloc(GetProcessHeap(), 0, cbSize * sizeof(WCHAR));
593 if (!ProfilePath)
594 {
595 WARN("HeapAlloc() failed\n");
596 goto cleanup;
597 }
598 bResult = GetProfilesDirectoryW(ProfilePath, &cbSize);
599 }
600 if (!bResult)
601 {
602 WARN("GetUserProfileDirectoryW() failed\n");
603 goto cleanup;
604 }
605
606 /* Allocate memory for profile */
607 pProfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WLX_PROFILE_V2_0));
608 if (!pProfile)
609 {
610 WARN("HeapAlloc() failed\n");
611 goto cleanup;
612 }
613 pProfile->dwType = WLX_PROFILE_TYPE_V2_0;
614 pProfile->pszProfile = ProfilePath;
615
616 lpEnvironment = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
617 (wcslen(pgContext->Domain)+ 14 + 1) * sizeof(WCHAR));
618 if (!lpEnvironment)
619 {
620 WARN("HeapAlloc() failed\n");
621 goto cleanup;
622 }
623
624 wsprintfW(lpEnvironment, L"LOGONSERVER=\\\\%s", pgContext->Domain);
625
626 pProfile->pszEnvironment = lpEnvironment;
627
628 if (!GetTokenInformation(pgContext->UserToken,
629 TokenStatistics,
630 (PVOID)&Stats,
631 sizeof(TOKEN_STATISTICS),
632 &cbStats))
633 {
634 WARN("Couldn't get Authentication id from user token!\n");
635 goto cleanup;
636 }
637
638 *pgContext->pAuthenticationId = Stats.AuthenticationId;
639 pgContext->pMprNotifyInfo->pszUserName = DuplicationString(UserName);
640 pgContext->pMprNotifyInfo->pszDomain = DuplicationString(Domain);
641 pgContext->pMprNotifyInfo->pszPassword = DuplicationString(Password);
642 pgContext->pMprNotifyInfo->pszOldPassword = NULL;
643 *pgContext->pdwOptions = 0;
644 *pgContext->pProfile = pProfile;
645 return TRUE;
646
647 cleanup:
648 if (pProfile)
649 {
650 HeapFree(GetProcessHeap(), 0, pProfile->pszEnvironment);
651 }
652 HeapFree(GetProcessHeap(), 0, pProfile);
653 HeapFree(GetProcessHeap(), 0, ProfilePath);
654 return FALSE;
655 }
656
657 #if 0
658 static
659 BOOL
660 CheckAutoAdminLogon(
661 IN PGINA_CONTEXT pgContext)
662 {
663 HKEY WinLogonKey = NULL;
664 LPWSTR AutoLogon = NULL;
665 BOOL result = FALSE;
666 LONG rc;
667
668 if (pgContext->AutoLogonState == AUTOLOGON_DISABLED)
669 return FALSE;
670
671 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
672 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon",
673 0,
674 KEY_QUERY_VALUE,
675 &WinLogonKey);
676 if (rc != ERROR_SUCCESS)
677 goto cleanup;
678
679 rc = ReadRegSzKey(WinLogonKey,
680 L"AutoAdminLogon",
681 &AutoLogon);
682
683 if (rc != ERROR_SUCCESS)
684 goto cleanup;
685
686 if (wcscmp(AutoLogon, L"1") == 0)
687 result = TRUE;
688
689 cleanup:
690 if (WinLogonKey != NULL)
691 RegCloseKey(WinLogonKey);
692 HeapFree(GetProcessHeap(), 0, AutoLogon);
693
694 return result;
695 }
696 #endif
697
698 static BOOL
699 DoAutoLogon(
700 IN PGINA_CONTEXT pgContext)
701 {
702 HKEY WinLogonKey = NULL;
703 LPWSTR AutoLogon = NULL;
704 LPWSTR AutoCount = NULL;
705 LPWSTR IgnoreShiftOverride = NULL;
706 LPWSTR UserName = NULL;
707 LPWSTR DomainName = NULL;
708 LPWSTR Password = NULL;
709 BOOL result = FALSE;
710 LONG rc;
711
712 TRACE("DoAutoLogon(): AutoLogonState = %lu\n",
713 pgContext->AutoLogonState);
714
715 if (pgContext->AutoLogonState == AUTOLOGON_DISABLED)
716 return FALSE;
717
718 rc = RegOpenKeyExW(
719 HKEY_LOCAL_MACHINE,
720 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon",
721 0,
722 KEY_QUERY_VALUE,
723 &WinLogonKey);
724 if (rc != ERROR_SUCCESS)
725 goto cleanup;
726
727 if (pgContext->AutoLogonState == AUTOLOGON_CHECK_REGISTRY)
728 {
729 /* Set it by default to disabled, we might reenable it again later */
730 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
731
732 rc = ReadRegSzKey(WinLogonKey, L"AutoAdminLogon", &AutoLogon);
733 if (rc != ERROR_SUCCESS)
734 goto cleanup;
735 if (wcscmp(AutoLogon, L"1") != 0)
736 goto cleanup;
737
738 rc = ReadRegSzKey(WinLogonKey, L"AutoLogonCount", &AutoCount);
739 if (rc == ERROR_SUCCESS && wcscmp(AutoCount, L"0") == 0)
740 goto cleanup;
741 else if (rc != ERROR_FILE_NOT_FOUND)
742 goto cleanup;
743
744 rc = ReadRegSzKey(WinLogonKey, L"IgnoreShiftOverride", &UserName);
745 if (rc == ERROR_SUCCESS)
746 {
747 if (wcscmp(AutoLogon, L"1") != 0 && GetKeyState(VK_SHIFT) < 0)
748 goto cleanup;
749 }
750 else if (GetKeyState(VK_SHIFT) < 0)
751 {
752 /* User pressed SHIFT */
753 goto cleanup;
754 }
755
756 pgContext->AutoLogonState = AUTOLOGON_ONCE;
757 result = TRUE;
758 }
759 else /* pgContext->AutoLogonState == AUTOLOGON_ONCE */
760 {
761 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
762
763 rc = ReadRegSzKey(WinLogonKey, L"DefaultUserName", &UserName);
764 if (rc != ERROR_SUCCESS)
765 goto cleanup;
766 rc = ReadRegSzKey(WinLogonKey, L"DefaultDomainName", &DomainName);
767 if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND)
768 goto cleanup;
769 rc = ReadRegSzKey(WinLogonKey, L"DefaultPassword", &Password);
770 if (rc != ERROR_SUCCESS)
771 goto cleanup;
772
773 result = DoLoginTasks(pgContext, UserName, DomainName, Password);
774
775 if (result == TRUE)
776 NotifyBootConfigStatus(TRUE);
777 }
778
779 cleanup:
780 if (WinLogonKey != NULL)
781 RegCloseKey(WinLogonKey);
782 HeapFree(GetProcessHeap(), 0, AutoLogon);
783 HeapFree(GetProcessHeap(), 0, AutoCount);
784 HeapFree(GetProcessHeap(), 0, IgnoreShiftOverride);
785 HeapFree(GetProcessHeap(), 0, UserName);
786 HeapFree(GetProcessHeap(), 0, DomainName);
787 HeapFree(GetProcessHeap(), 0, Password);
788 TRACE("DoAutoLogon(): AutoLogonState = %lu, returning %d\n",
789 pgContext->AutoLogonState, result);
790 return result;
791 }
792
793 /*
794 * @implemented
795 */
796 VOID WINAPI
797 WlxDisplaySASNotice(
798 IN PVOID pWlxContext)
799 {
800 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
801
802 TRACE("WlxDisplaySASNotice(%p)\n", pWlxContext);
803
804 if (GetSystemMetrics(SM_REMOTESESSION))
805 {
806 /* User is remotely logged on. Don't display a notice */
807 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
808 return;
809 }
810
811 // if (CheckAutoAdminLogon(pgContext))
812 if (pgContext->bAutoAdminLogon == TRUE)
813 {
814 /* Don't display the window, we want to do an automatic logon */
815 pgContext->AutoLogonState = AUTOLOGON_ONCE;
816 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
817 return;
818 }
819 else
820 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
821
822 if (pgContext->bDisableCAD == TRUE)
823 {
824 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
825 return;
826 }
827
828 pGinaUI->DisplaySASNotice(pgContext);
829
830 TRACE("WlxDisplaySASNotice() done\n");
831 }
832
833 /*
834 * @implemented
835 */
836 INT WINAPI
837 WlxLoggedOutSAS(
838 IN PVOID pWlxContext,
839 IN DWORD dwSasType,
840 OUT PLUID pAuthenticationId,
841 IN OUT PSID pLogonSid,
842 OUT PDWORD pdwOptions,
843 OUT PHANDLE phToken,
844 OUT PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
845 OUT PVOID *pProfile)
846 {
847 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
848 INT res;
849
850 TRACE("WlxLoggedOutSAS()\n");
851
852 UNREFERENCED_PARAMETER(dwSasType);
853 UNREFERENCED_PARAMETER(pLogonSid);
854
855 pgContext->pAuthenticationId = pAuthenticationId;
856 pgContext->pdwOptions = pdwOptions;
857 pgContext->pMprNotifyInfo = pMprNotifyInfo;
858 pgContext->pProfile = pProfile;
859
860 if (0 == GetSystemMetrics(SM_REMOTESESSION) &&
861 DoAutoLogon(pgContext))
862 {
863 /* User is local and registry contains information
864 * to log on him automatically */
865 *phToken = pgContext->UserToken;
866 return WLX_SAS_ACTION_LOGON;
867 }
868
869 res = pGinaUI->LoggedOutSAS(pgContext);
870 *phToken = pgContext->UserToken;
871 return res;
872 }
873
874 /*
875 * @implemented
876 */
877 int WINAPI
878 WlxWkstaLockedSAS(
879 PVOID pWlxContext,
880 DWORD dwSasType)
881 {
882 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
883
884 TRACE("WlxWkstaLockedSAS()\n");
885
886 UNREFERENCED_PARAMETER(dwSasType);
887
888 return pGinaUI->LockedSAS(pgContext);
889 }
890
891
892 /*
893 * @implemented
894 */
895 VOID
896 WINAPI
897 WlxDisplayLockedNotice(PVOID pWlxContext)
898 {
899 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
900
901 TRACE("WlxDisplayLockedNotice()\n");
902
903 if (pgContext->bDisableCAD == TRUE)
904 {
905 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
906 return;
907 }
908
909 pGinaUI->DisplayLockedNotice(pgContext);
910 }
911
912
913 /*
914 * @implemented
915 */
916 BOOL WINAPI
917 WlxIsLogoffOk(
918 PVOID pWlxContext)
919 {
920 TRACE("WlxIsLogoffOk()\n");
921 UNREFERENCED_PARAMETER(pWlxContext);
922 return TRUE;
923 }
924
925 BOOL WINAPI
926 DllMain(
927 IN HINSTANCE hinstDLL,
928 IN DWORD dwReason,
929 IN LPVOID lpvReserved)
930 {
931 UNREFERENCED_PARAMETER(lpvReserved);
932
933 if (dwReason == DLL_PROCESS_ATTACH)
934 hDllInstance = hinstDLL;
935
936 return TRUE;
937 }