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