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