reactos/base/system/winlogon/wlx.c

1339 lines
32 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Winlogon
* FILE: base/system/winlogon/wlx.c
* PURPOSE: Logon
* PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
* Ge van Geldorp (gvg@reactos.com)
* Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES *****************************************************************/
#include "winlogon.h"
#define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \
DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)
#define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \
WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \
WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \
STANDARD_RIGHTS_REQUIRED)
#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \
GENERIC_EXECUTE | GENERIC_ALL)
typedef struct _DIALOG_LIST_ENTRY
{
LIST_ENTRY Entry;
HWND hWnd;
DLGPROC DlgProc;
LPARAM lParam;
} DIALOG_LIST_ENTRY, *PDIALOG_LIST_ENTRY;
/* GLOBALS ******************************************************************/
//static UINT_PTR IdTimer;
static LIST_ENTRY DialogListHead;
/* FUNCTIONS ****************************************************************/
VOID
InitDialogListHead(VOID)
{
InitializeListHead(&DialogListHead);
}
static
PDIALOG_LIST_ENTRY
AddDialogListEntry(VOID)
{
PDIALOG_LIST_ENTRY ListEntry;
ListEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DIALOG_LIST_ENTRY));
if (ListEntry == NULL)
return NULL;
TRACE("Add entry %p\n", ListEntry);
InsertHeadList(&DialogListHead,
&ListEntry->Entry);
return ListEntry;
}
static
VOID
RemoveDialogListEntry(PDIALOG_LIST_ENTRY ListEntry)
{
TRACE("Remove entry %p\n", ListEntry);
RemoveEntryList(&ListEntry->Entry);
RtlFreeHeap(RtlGetProcessHeap(), 0, ListEntry);
}
static
PDIALOG_LIST_ENTRY
GetDialogListEntry(HWND hwndDlg)
{
PDIALOG_LIST_ENTRY Current;
PLIST_ENTRY ListEntry;
ListEntry = DialogListHead.Flink;
while (ListEntry != &DialogListHead)
{
Current = CONTAINING_RECORD(ListEntry,
DIALOG_LIST_ENTRY,
Entry);
if (Current->hWnd == hwndDlg)
{
TRACE("Found entry: %p\n", Current);
return Current;
}
ListEntry = ListEntry->Flink;
}
TRACE("Found no entry!\n");
return NULL;
}
VOID
CloseAllDialogWindows(VOID)
{
PDIALOG_LIST_ENTRY Current;
PLIST_ENTRY ListEntry;
ListEntry = DialogListHead.Flink;
while (ListEntry != &DialogListHead)
{
Current = CONTAINING_RECORD(ListEntry,
DIALOG_LIST_ENTRY,
Entry);
PostMessage(Current->hWnd, WLX_WM_SAS, 0, 0);
ListEntry = ListEntry->Flink;
}
}
static
INT_PTR
CALLBACK
DefaultWlxWindowProc(
IN HWND hwndDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam)
{
PDIALOG_LIST_ENTRY ListEntry;
INT_PTR ret;
if (uMsg == WM_INITDIALOG)
{
ListEntry = (PDIALOG_LIST_ENTRY)lParam;
TRACE("Set dialog handle: %p\n", hwndDlg);
ListEntry->hWnd = hwndDlg;
lParam = ListEntry->lParam;
// SetTopTimeout(hWnd);
}
else
{
ListEntry = GetDialogListEntry(hwndDlg);
if (ListEntry == NULL)
return FALSE;
}
if (uMsg == WLX_WM_SAS)
{
EndDialog(hwndDlg, WLX_DLG_SAS);
return 0;
}
ret = ListEntry->DlgProc(hwndDlg, uMsg, wParam, lParam);
return ret;
/*
if (uMsg == WM_TIMER && (UINT_PTR)wParam == IdTimer)
{
EndDialog(hwndDlg, -1);
KillTimer(hwndDlg, IdTimer);
return TRUE;
}
else if (uMsg == WM_INITDIALOG)
{
IdTimer = SetTimer(hwndDlg, 0, WLSession->DialogTimeout * 1000, NULL);
return PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
}
else if (uMsg == WM_NCDESTROY)
{
BOOL ret;
ret = PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
PreviousWindowProc = NULL;
return ret;
}
else
{
return PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
}
*/
}
/*
* @implemented
*/
VOID
WINAPI
WlxUseCtrlAltDel(
HANDLE hWlx)
{
ULONG_PTR OldValue;
TRACE("WlxUseCtrlAltDel()\n");
WlxSetOption(hWlx, WLX_OPTION_USE_CTRL_ALT_DEL, TRUE, &OldValue);
}
/*
* @implemented
*/
VOID
WINAPI
WlxSetContextPointer(
HANDLE hWlx,
PVOID pWlxContext)
{
ULONG_PTR OldValue;
TRACE("WlxSetContextPointer(%p)\n", pWlxContext);
WlxSetOption(hWlx, WLX_OPTION_CONTEXT_POINTER, (ULONG_PTR)pWlxContext, &OldValue);
}
/*
* @implemented
*/
VOID
WINAPI
WlxSasNotify(
HANDLE hWlx,
DWORD dwSasType)
{
PWLSESSION Session = (PWLSESSION)hWlx;
TRACE("WlxSasNotify(0x%lx)\n", dwSasType);
if (dwSasType == WLX_SAS_TYPE_CTRL_ALT_DEL || dwSasType > WLX_SAS_TYPE_MAX_MSFT_VALUE)
PostMessageW(Session->SASWindow, WLX_WM_SAS, dwSasType, 0);
}
/*
* @implemented
*/
BOOL
WINAPI
WlxSetTimeout(
HANDLE hWlx,
DWORD Timeout)
{
PWLSESSION Session = (PWLSESSION)hWlx;
TRACE("WlxSetTimeout(%lu)\n", Timeout);
Session->DialogTimeout = Timeout;
return TRUE;
}
/*
* @unimplemented
*/
int
WINAPI
WlxAssignShellProtection(
HANDLE hWlx,
HANDLE hToken,
HANDLE hProcess,
HANDLE hThread)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(hToken);
UNREFERENCED_PARAMETER(hProcess);
UNREFERENCED_PARAMETER(hThread);
UNIMPLEMENTED;
return 0;
}
/*
* @implemented
*/
int
WINAPI
WlxMessageBox(
HANDLE hWlx,
HWND hwndOwner,
LPWSTR lpszText,
LPWSTR lpszTitle,
UINT fuStyle)
{
UNREFERENCED_PARAMETER(hWlx);
TRACE("WlxMessageBox()\n");
/* FIXME: Provide a custom window proc to be able to handle timeout */
return MessageBoxW(hwndOwner, lpszText, lpszTitle, fuStyle);
}
/*
* @implemented
*/
int
WINAPI
WlxDialogBox(
HANDLE hWlx,
HANDLE hInst,
LPWSTR lpszTemplate,
HWND hwndOwner,
DLGPROC dlgprc)
{
UNREFERENCED_PARAMETER(hWlx);
TRACE("WlxDialogBox()\n");
return (int)WlxDialogBoxParam(hWlx, hInst, lpszTemplate, hwndOwner, dlgprc, 0);
}
/*
* @implemented
*/
int
WINAPI
WlxDialogBoxParam(
HANDLE hWlx,
HANDLE hInst,
LPWSTR lpszTemplate,
HWND hwndOwner,
DLGPROC dlgprc,
LPARAM dwInitParam)
{
PDIALOG_LIST_ENTRY ListEntry;
int ret;
UNREFERENCED_PARAMETER(hWlx);
TRACE("WlxDialogBoxParam()\n");
ListEntry = AddDialogListEntry();
if (ListEntry == NULL)
return -1;
ListEntry->DlgProc = dlgprc;
ListEntry->lParam = dwInitParam;
ret = (int)DialogBoxParamW(hInst, lpszTemplate, hwndOwner, DefaultWlxWindowProc, (LPARAM)ListEntry);
RemoveDialogListEntry(ListEntry);
return ret;
}
/*
* @implemented
*/
int
WINAPI
WlxDialogBoxIndirect(
HANDLE hWlx,
HANDLE hInst,
LPCDLGTEMPLATE hDialogTemplate,
HWND hwndOwner,
DLGPROC dlgprc)
{
UNREFERENCED_PARAMETER(hWlx);
TRACE("WlxDialogBoxIndirect()\n");
return (int)WlxDialogBoxIndirectParam(hWlx, hInst, hDialogTemplate, hwndOwner, dlgprc, 0);
}
/*
* @implemented
*/
int
WINAPI
WlxDialogBoxIndirectParam(
HANDLE hWlx,
HANDLE hInst,
LPCDLGTEMPLATE hDialogTemplate,
HWND hwndOwner,
DLGPROC dlgprc,
LPARAM dwInitParam)
{
PDIALOG_LIST_ENTRY ListEntry;
int ret;
UNREFERENCED_PARAMETER(hWlx);
TRACE("WlxDialogBoxIndirectParam()\n");
ListEntry = AddDialogListEntry();
if (ListEntry == NULL)
return -1;
ListEntry->DlgProc = dlgprc;
ListEntry->lParam = dwInitParam;
ret = (int)DialogBoxIndirectParamW(hInst, hDialogTemplate, hwndOwner, DefaultWlxWindowProc, (LPARAM)ListEntry);
RemoveDialogListEntry(ListEntry);
return ret;
}
/*
* @implemented
*/
int
WINAPI
WlxSwitchDesktopToUser(
HANDLE hWlx)
{
PWLSESSION Session = (PWLSESSION)hWlx;
TRACE("WlxSwitchDesktopToUser()\n");
return (int)SwitchDesktop(Session->ApplicationDesktop);
}
/*
* @implemented
*/
int
WINAPI
WlxSwitchDesktopToWinlogon(
HANDLE hWlx)
{
PWLSESSION Session = (PWLSESSION)hWlx;
TRACE("WlxSwitchDesktopToWinlogon()\n");
return (int)SwitchDesktop(Session->WinlogonDesktop);
}
/*
* @unimplemented
*/
int
WINAPI
WlxChangePasswordNotify(
HANDLE hWlx,
PWLX_MPR_NOTIFY_INFO pMprInfo,
DWORD dwChangeInfo)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(pMprInfo);
UNREFERENCED_PARAMETER(dwChangeInfo);
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxGetSourceDesktop(
HANDLE hWlx,
PWLX_DESKTOP* ppDesktop)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(ppDesktop);
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxSetReturnDesktop(
HANDLE hWlx,
PWLX_DESKTOP pDesktop)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(pDesktop);
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxCreateUserDesktop(
HANDLE hWlx,
HANDLE hToken,
DWORD Flags,
PWSTR pszDesktopName,
PWLX_DESKTOP* ppDesktop)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(hToken);
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(pszDesktopName);
UNREFERENCED_PARAMETER(ppDesktop);
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
int
WINAPI
WlxChangePasswordNotifyEx(
HANDLE hWlx,
PWLX_MPR_NOTIFY_INFO pMprInfo,
DWORD dwChangeInfo,
PWSTR ProviderName,
PVOID Reserved)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(pMprInfo);
UNREFERENCED_PARAMETER(dwChangeInfo);
UNREFERENCED_PARAMETER(ProviderName);
UNREFERENCED_PARAMETER(Reserved);
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxCloseUserDesktop(
HANDLE hWlx,
PWLX_DESKTOP pDesktop,
HANDLE hToken)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(pDesktop);
UNREFERENCED_PARAMETER(hToken);
UNIMPLEMENTED;
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
WlxSetOption(
HANDLE hWlx,
DWORD Option,
ULONG_PTR Value,
ULONG_PTR* OldValue)
{
PWLSESSION Session = (PWLSESSION)hWlx;
TRACE("WlxSetOption(%lu)\n", Option);
switch (Option)
{
case WLX_OPTION_USE_CTRL_ALT_DEL:
*OldValue = (ULONG_PTR)Session->Gina.UseCtrlAltDelete;
Session->Gina.UseCtrlAltDelete = (BOOL)Value;
return TRUE;
case WLX_OPTION_CONTEXT_POINTER:
*OldValue = (ULONG_PTR)Session->Gina.Context;
Session->Gina.Context = (PVOID)Value;
return TRUE;
case WLX_OPTION_USE_SMART_CARD:
UNIMPLEMENTED;
return FALSE;
}
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
WlxGetOption(
HANDLE hWlx,
DWORD Option,
ULONG_PTR* Value)
{
PWLSESSION Session = (PWLSESSION)hWlx;
TRACE("WlxGetOption(%lu)\n", Option);
switch (Option)
{
case WLX_OPTION_USE_CTRL_ALT_DEL:
*Value = (ULONG_PTR)Session->Gina.UseCtrlAltDelete;
return TRUE;
case WLX_OPTION_CONTEXT_POINTER:
{
*Value = (ULONG_PTR)Session->Gina.Context;
return TRUE;
}
case WLX_OPTION_USE_SMART_CARD:
case WLX_OPTION_SMART_CARD_PRESENT:
case WLX_OPTION_SMART_CARD_INFO:
UNIMPLEMENTED;
return FALSE;
case WLX_OPTION_DISPATCH_TABLE_SIZE:
{
switch (Session->Gina.Version)
{
case WLX_VERSION_1_0:
*Value = sizeof(WLX_DISPATCH_VERSION_1_0);
break;
case WLX_VERSION_1_1:
*Value = sizeof(WLX_DISPATCH_VERSION_1_1);
break;
case WLX_VERSION_1_2:
*Value = sizeof(WLX_DISPATCH_VERSION_1_2);
break;
case WLX_VERSION_1_3:
*Value = sizeof(WLX_DISPATCH_VERSION_1_3);
break;
case WLX_VERSION_1_4:
*Value = sizeof(WLX_DISPATCH_VERSION_1_4);
break;
default:
return FALSE;
}
return TRUE;
}
}
return FALSE;
}
/*
* @unimplemented
*/
VOID
WINAPI
WlxWin31Migrate(
HANDLE hWlx)
{
UNREFERENCED_PARAMETER(hWlx);
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxQueryClientCredentials(
PWLX_CLIENT_CREDENTIALS_INFO_V1_0 pCred)
{
UNREFERENCED_PARAMETER(pCred);
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxQueryInetConnectorCredentials(
PWLX_CLIENT_CREDENTIALS_INFO_V1_0 pCred)
{
UNREFERENCED_PARAMETER(pCred);
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxDisconnect(VOID)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
DWORD
WINAPI
WlxQueryTerminalServicesData(
HANDLE hWlx,
PWLX_TERMINAL_SERVICES_DATA pTSData,
WCHAR* UserName,
WCHAR* Domain)
{
UNREFERENCED_PARAMETER(hWlx);
UNREFERENCED_PARAMETER(pTSData);
UNREFERENCED_PARAMETER(UserName);
UNREFERENCED_PARAMETER(Domain);
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/
DWORD
WINAPI
WlxQueryConsoleSwitchCredentials(
PWLX_CONSOLESWITCH_CREDENTIALS_INFO_V1_0 pCred)
{
UNREFERENCED_PARAMETER(pCred);
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/
BOOL
WINAPI
WlxQueryTsLogonCredentials(
PWLX_CLIENT_CREDENTIALS_INFO_V2_0 pCred)
{
UNREFERENCED_PARAMETER(pCred);
UNIMPLEMENTED;
return FALSE;
}
static
WLX_DISPATCH_VERSION_1_4 FunctionTable = {
WlxUseCtrlAltDel,
WlxSetContextPointer,
WlxSasNotify,
WlxSetTimeout,
WlxAssignShellProtection,
WlxMessageBox,
WlxDialogBox,
WlxDialogBoxParam,
WlxDialogBoxIndirect,
WlxDialogBoxIndirectParam,
WlxSwitchDesktopToUser,
WlxSwitchDesktopToWinlogon,
WlxChangePasswordNotify,
WlxGetSourceDesktop,
WlxSetReturnDesktop,
WlxCreateUserDesktop,
WlxChangePasswordNotifyEx,
WlxCloseUserDesktop,
WlxSetOption,
WlxGetOption,
WlxWin31Migrate,
WlxQueryClientCredentials,
WlxQueryInetConnectorCredentials,
WlxDisconnect,
WlxQueryTerminalServicesData,
WlxQueryConsoleSwitchCredentials,
WlxQueryTsLogonCredentials
};
/******************************************************************************/
static
BOOL
GetGinaPath(
OUT LPWSTR Path,
IN DWORD Len)
{
LONG Status;
DWORD Type, Size;
HKEY hKey;
Status = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
0,
KEY_QUERY_VALUE,
&hKey);
if (Status != ERROR_SUCCESS)
{
/* Default value */
wcsncpy(Path, L"msgina.dll", Len);
return TRUE;
}
Size = Len * sizeof(WCHAR);
Status = RegQueryValueExW(
hKey,
L"GinaDLL",
NULL,
&Type,
(LPBYTE)Path,
&Size);
if (Status != ERROR_SUCCESS || Type != REG_SZ || Size == 0)
wcsncpy(Path, L"msgina.dll", Len);
RegCloseKey(hKey);
return TRUE;
}
static
BOOL
WINAPI
DefaultWlxScreenSaverNotify(
IN PVOID pWlxContext,
IN OUT BOOL *pSecure)
{
if (*pSecure)
*pSecure = WLSession->Gina.Functions.WlxIsLogoffOk(pWlxContext);
return TRUE;
}
static
BOOL
LoadGina(
IN OUT PGINAFUNCTIONS Functions,
OUT DWORD *DllVersion,
OUT HMODULE *GinaInstance)
{
HMODULE hGina = NULL;
WCHAR GinaDll[MAX_PATH + 1];
BOOL ret = FALSE;
GinaDll[0] = '\0';
if (!GetGinaPath(GinaDll, MAX_PATH))
goto cleanup;
/* Terminate string */
GinaDll[MAX_PATH] = '\0';
hGina = LoadLibraryW(GinaDll);
if (!hGina)
goto cleanup;
Functions->WlxNegotiate = (PFWLXNEGOTIATE)GetProcAddress(hGina, "WlxNegotiate");
Functions->WlxInitialize = (PFWLXINITIALIZE)GetProcAddress(hGina, "WlxInitialize");
if (!Functions->WlxInitialize)
goto cleanup;
if (!Functions->WlxNegotiate)
{
/* Assume current version */
*DllVersion = WLX_CURRENT_VERSION;
}
else
{
TRACE("About to negotiate with Gina %S. Winlogon uses version %x\n",
GinaDll, WLX_CURRENT_VERSION);
if (!Functions->WlxNegotiate(WLX_CURRENT_VERSION, DllVersion))
goto cleanup;
}
TRACE("Gina uses WLX_VERSION %lx\n", *DllVersion);
if (*DllVersion >= WLX_VERSION_1_0)
{
Functions->WlxActivateUserShell = (PFWLXACTIVATEUSERSHELL)GetProcAddress(hGina, "WlxActivateUserShell");
if (!Functions->WlxActivateUserShell) goto cleanup;
Functions->WlxDisplayLockedNotice = (PFWLXDISPLAYLOCKEDNOTICE)GetProcAddress(hGina, "WlxDisplayLockedNotice");
if (!Functions->WlxDisplayLockedNotice) goto cleanup;
Functions->WlxDisplaySASNotice = (PFWLXDISPLAYSASNOTICE)GetProcAddress(hGina, "WlxDisplaySASNotice");
if (!Functions->WlxDisplaySASNotice) goto cleanup;
Functions->WlxIsLockOk = (PFWLXISLOCKOK)GetProcAddress(hGina, "WlxIsLockOk");
if (!Functions->WlxIsLockOk) goto cleanup;
Functions->WlxIsLogoffOk = (PFWLXISLOGOFFOK)GetProcAddress(hGina, "WlxIsLogoffOk");
if (!Functions->WlxIsLogoffOk) goto cleanup;
Functions->WlxLoggedOnSAS = (PFWLXLOGGEDONSAS)GetProcAddress(hGina, "WlxLoggedOnSAS");
if (!Functions->WlxLoggedOnSAS) goto cleanup;
Functions->WlxLoggedOutSAS = (PFWLXLOGGEDOUTSAS)GetProcAddress(hGina, "WlxLoggedOutSAS");
if (!Functions->WlxLoggedOutSAS) goto cleanup;
Functions->WlxLogoff = (PFWLXLOGOFF)GetProcAddress(hGina, "WlxLogoff");
if (!Functions->WlxLogoff) goto cleanup;
Functions->WlxShutdown = (PFWLXSHUTDOWN)GetProcAddress(hGina, "WlxShutdown");
if (!Functions->WlxShutdown) goto cleanup;
Functions->WlxWkstaLockedSAS = (PFWLXWKSTALOCKEDSAS)GetProcAddress(hGina, "WlxWkstaLockedSAS");
if (!Functions->WlxWkstaLockedSAS) goto cleanup;
}
if (*DllVersion >= WLX_VERSION_1_1)
{
Functions->WlxScreenSaverNotify = (PFWLXSCREENSAVERNOTIFY)GetProcAddress(hGina, "WlxScreenSaverNotify");
Functions->WlxStartApplication = (PFWLXSTARTAPPLICATION)GetProcAddress(hGina, "WlxStartApplication");
}
if (*DllVersion >= WLX_VERSION_1_3)
{
Functions->WlxDisplayStatusMessage = (PFWLXDISPLAYSTATUSMESSAGE)GetProcAddress(hGina, "WlxDisplayStatusMessage");
if (!Functions->WlxDisplayStatusMessage) goto cleanup;
Functions->WlxGetStatusMessage = (PFWLXGETSTATUSMESSAGE)GetProcAddress(hGina, "WlxGetStatusMessage");
if (!Functions->WlxGetStatusMessage) goto cleanup;
Functions->WlxNetworkProviderLoad = (PFWLXNETWORKPROVIDERLOAD)GetProcAddress(hGina, "WlxNetworkProviderLoad");
if (!Functions->WlxNetworkProviderLoad) goto cleanup;
Functions->WlxRemoveStatusMessage = (PFWLXREMOVESTATUSMESSAGE)GetProcAddress(hGina, "WlxRemoveStatusMessage");
if (!Functions->WlxRemoveStatusMessage) goto cleanup;
}
/* Provide some default functions */
if (!Functions->WlxScreenSaverNotify)
Functions->WlxScreenSaverNotify = DefaultWlxScreenSaverNotify;
ret = TRUE;
cleanup:
if (!ret)
{
if (hGina)
FreeLibrary(hGina);
}
else
*GinaInstance = hGina;
return ret;
}
BOOL
GinaInit(
IN OUT PWLSESSION Session)
{
DWORD GinaDllVersion;
if (!LoadGina(&Session->Gina.Functions, &GinaDllVersion, &Session->Gina.hDllInstance))
return FALSE;
Session->Gina.Context = NULL;
Session->Gina.Version = GinaDllVersion;
Session->Gina.UseCtrlAltDelete = FALSE;
Session->SuppressStatus = FALSE;
TRACE("Calling WlxInitialize(\"%S\")\n", Session->InteractiveWindowStationName);
return Session->Gina.Functions.WlxInitialize(
Session->InteractiveWindowStationName,
(HANDLE)Session,
NULL,
(PVOID)&FunctionTable,
&Session->Gina.Context);
}
BOOL
AddAceToWindowStation(
IN HWINSTA WinSta,
IN PSID Sid)
{
DWORD AclSize;
SECURITY_INFORMATION SecurityInformation;
PACL pDefaultAcl = NULL;
PSECURITY_DESCRIPTOR WinstaSd = NULL;
PACCESS_ALLOWED_ACE Ace = NULL;
BOOL Ret = FALSE;
/* Allocate space for an ACL */
AclSize = sizeof(ACL)
+ 2 * (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(Sid));
pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
if (!pDefaultAcl)
{
ERR("WL: HeapAlloc() failed\n");
goto cleanup;
}
/* Initialize it */
if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION))
{
ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Initialize new security descriptor */
WinstaSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!InitializeSecurityDescriptor(WinstaSd, SECURITY_DESCRIPTOR_REVISION))
{
ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Allocate memory for access allowed ACE */
Ace = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE)+
GetLengthSid(Sid) - sizeof(DWORD));
/* Create the first ACE for the window station */
Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
Ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
Ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(Sid) - sizeof(DWORD);
Ace->Mask = GENERIC_ACCESS;
/* Copy the sid */
if (!CopySid(GetLengthSid(Sid), &Ace->SidStart, Sid))
{
ERR("WL: CopySid() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Add the first ACE */
if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize))
{
ERR("WL: AddAce() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Add the second ACE to the end of ACL */
Ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
Ace->Mask = WINSTA_ALL;
if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize))
{
ERR("WL: AddAce() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Add ACL to winsta's security descriptor */
if (!SetSecurityDescriptorDacl(WinstaSd, TRUE, pDefaultAcl, FALSE))
{
ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Apply security to the window station */
SecurityInformation = DACL_SECURITY_INFORMATION;
if (!SetUserObjectSecurity(WinSta, &SecurityInformation, WinstaSd))
{
ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Indicate success */
Ret = TRUE;
cleanup:
/* Free allocated stuff */
if (pDefaultAcl) HeapFree(GetProcessHeap(), 0, pDefaultAcl);
if (WinstaSd) HeapFree(GetProcessHeap(), 0, WinstaSd);
if (Ace) HeapFree(GetProcessHeap(), 0, Ace);
return Ret;
}
BOOL
AddAceToDesktop(
IN HDESK Desktop,
IN PSID WinlogonSid,
IN PSID UserSid)
{
DWORD AclSize;
SECURITY_INFORMATION SecurityInformation;
PACL Acl = NULL;
PSECURITY_DESCRIPTOR DesktopSd = NULL;
BOOL Ret = FALSE;
/* Allocate ACL */
AclSize = sizeof(ACL)
+ FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(WinlogonSid);
/* Take user's sid into account */
if (UserSid)
AclSize += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(UserSid);
Acl = HeapAlloc(GetProcessHeap(), 0, AclSize);
if (!Acl)
{
ERR("WL: HeapAlloc() failed\n");
goto cleanup;
}
/* Initialize ACL */
if (!InitializeAcl(Acl, AclSize, ACL_REVISION))
{
ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Add full desktop access ACE for winlogon */
if (!AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, WinlogonSid))
{
ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Add full desktop access ACE for a user (if provided) */
if (UserSid && !AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, UserSid))
{
ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Initialize new security descriptor */
DesktopSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!InitializeSecurityDescriptor(DesktopSd, SECURITY_DESCRIPTOR_REVISION))
{
ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Add ACL to the security descriptor */
if (!SetSecurityDescriptorDacl(DesktopSd, TRUE, Acl, FALSE))
{
ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Apply security to the window station */
SecurityInformation = DACL_SECURITY_INFORMATION;
if (!SetUserObjectSecurity(Desktop, &SecurityInformation, DesktopSd))
{
ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/* Indicate success */
Ret = TRUE;
cleanup:
/* Free allocated stuff */
if (Acl) HeapFree(GetProcessHeap(), 0, Acl);
if (DesktopSd) HeapFree(GetProcessHeap(), 0, DesktopSd);
return Ret;
}
BOOL
CreateWindowStationAndDesktops(
IN OUT PWLSESSION Session)
{
BYTE LocalSystemBuffer[SECURITY_MAX_SID_SIZE];
BYTE InteractiveBuffer[SECURITY_MAX_SID_SIZE];
PSID pLocalSystemSid = (PSID)&LocalSystemBuffer;
PSID pInteractiveSid = (PSID)InteractiveBuffer;
DWORD SidSize, AclSize;
PACL pDefaultAcl = NULL;
PACL pUserDesktopAcl = NULL;
SECURITY_DESCRIPTOR DefaultSecurityDescriptor;
SECURITY_ATTRIBUTES DefaultSecurity;
SECURITY_DESCRIPTOR UserDesktopSecurityDescriptor;
SECURITY_ATTRIBUTES UserDesktopSecurity;
BOOL ret = FALSE;
/*
* Prepare information for ACLs we will apply
*/
SidSize = SECURITY_MAX_SID_SIZE;
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, pLocalSystemSid, &SidSize))
{
ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError());
goto cleanup;
}
SidSize = SECURITY_MAX_SID_SIZE;
if (!CreateWellKnownSid(WinInteractiveSid, NULL, pInteractiveSid, &SidSize))
{
ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError());
goto cleanup;
}
AclSize = sizeof(ACL)
+ FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pLocalSystemSid)
+ FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pInteractiveSid);
pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
pUserDesktopAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
if (!pDefaultAcl || !pUserDesktopAcl)
{
ERR("WL: HeapAlloc() failed\n");
goto cleanup;
}
if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION)
|| !InitializeAcl(pUserDesktopAcl, AclSize, ACL_REVISION))
{
ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/*
* Create default ACL (window station, winlogon desktop, screen saver desktop)
*/
if (!AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid)
|| !AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_READ, pInteractiveSid))
{
ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/*
* Create the default security descriptor
*/
if (!InitializeSecurityDescriptor(&DefaultSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
{
ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
goto cleanup;
}
if (!SetSecurityDescriptorDacl(&DefaultSecurityDescriptor, TRUE, pDefaultAcl, FALSE))
{
ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
goto cleanup;
}
DefaultSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
DefaultSecurity.lpSecurityDescriptor = &DefaultSecurityDescriptor;
DefaultSecurity.bInheritHandle = TRUE;
/*
* Create user desktop ACL
*/
if (!AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid)
|| !AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pInteractiveSid))
{
ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/*
* Create the user desktop security descriptor
*/
if (!InitializeSecurityDescriptor(&UserDesktopSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
{
ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
goto cleanup;
}
if (!SetSecurityDescriptorDacl(&UserDesktopSecurityDescriptor, TRUE, pUserDesktopAcl, FALSE))
{
ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
goto cleanup;
}
UserDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
UserDesktopSecurity.lpSecurityDescriptor = &UserDesktopSecurityDescriptor;
UserDesktopSecurity.bInheritHandle = TRUE;
/*
* Create the interactive window station
*/
Session->InteractiveWindowStationName = L"WinSta0";
Session->InteractiveWindowStation = CreateWindowStationW(
Session->InteractiveWindowStationName,
0,
MAXIMUM_ALLOWED,
&DefaultSecurity);
if (!Session->InteractiveWindowStation)
{
ERR("WL: Failed to create window station (%lu)\n", GetLastError());
goto cleanup;
}
if (!SetProcessWindowStation(Session->InteractiveWindowStation))
{
ERR("WL: SetProcessWindowStation() failed (error %lu)\n", GetLastError());
goto cleanup;
}
/*
* Create the application desktop
*/
Session->ApplicationDesktop = CreateDesktopW(
L"Default",
NULL,
NULL,
0, /* FIXME: Add DF_ALLOWOTHERACCOUNTHOOK flag? */
MAXIMUM_ALLOWED,
&UserDesktopSecurity);
if (!Session->ApplicationDesktop)
{
ERR("WL: Failed to create Default desktop (%lu)\n", GetLastError());
goto cleanup;
}
/*
* Create the winlogon desktop
*/
Session->WinlogonDesktop = CreateDesktopW(
L"Winlogon",
NULL,
NULL,
0,
MAXIMUM_ALLOWED,
&DefaultSecurity); // FIXME: Must use restricted Winlogon-only security!!
if (!Session->WinlogonDesktop)
{
ERR("WL: Failed to create Winlogon desktop (%lu)\n", GetLastError());
goto cleanup;
}
/*
* Create the screen saver desktop
*/
Session->ScreenSaverDesktop = CreateDesktopW(
L"Screen-Saver",
NULL,
NULL,
0,
MAXIMUM_ALLOWED,
&DefaultSecurity);
if(!Session->ScreenSaverDesktop)
{
ERR("WL: Failed to create Screen-Saver desktop (%lu)\n", GetLastError());
goto cleanup;
}
/*
* Switch to winlogon desktop
*/
if (!SetThreadDesktop(Session->WinlogonDesktop) ||
!SwitchDesktop(Session->WinlogonDesktop))
{
ERR("WL: Cannot switch to Winlogon desktop (%lu)\n", GetLastError());
goto cleanup;
}
SetWindowStationUser(Session->InteractiveWindowStation,
&LuidNone, NULL, 0);
ret = TRUE;
cleanup:
if (!ret)
{
if (Session->ApplicationDesktop)
{
CloseDesktop(Session->ApplicationDesktop);
Session->ApplicationDesktop = NULL;
}
if (Session->WinlogonDesktop)
{
CloseDesktop(Session->WinlogonDesktop);
Session->WinlogonDesktop = NULL;
}
if (Session->ScreenSaverDesktop)
{
CloseDesktop(Session->ScreenSaverDesktop);
Session->ScreenSaverDesktop = NULL;
}
if (Session->InteractiveWindowStation)
{
CloseWindowStation(Session->InteractiveWindowStation);
Session->InteractiveWindowStation = NULL;
}
}
HeapFree(GetProcessHeap(), 0, pDefaultAcl);
HeapFree(GetProcessHeap(), 0, pUserDesktopAcl);
return ret;
}