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