reactos/base/system/winlogon/wlx.c
George Bișoc f96c39f6b0
[WINLOGON] Refactor the security management part
Refactor the security related code of Winlogon and move it to its own dedicated place, security.c. This includes code for preparation of security descriptors for window station and desktop objects when their created, helper functions which give allow access to such objects for the logged in user and whatnot.

==== DO NOTE ====
Currently new desktop security assignment fails because for whatever reason the system thinks the application desktop has no prior security even though a descriptor has been created for it before. See the FIXME comment on code for information.
2022-05-06 10:09:49 +02:00

1107 lines
25 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"
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
CreateWindowStationAndDesktops(
_Inout_ PWLSESSION Session)
{
SECURITY_ATTRIBUTES WinstaSecurity;
SECURITY_ATTRIBUTES ApplicationDesktopSecurity;
SECURITY_ATTRIBUTES WinlogonDesktopSecurity;
SECURITY_ATTRIBUTES ScreenSaverDesktopSecurity;
PSECURITY_DESCRIPTOR WlWinstaSecurityDescriptor;
PSECURITY_DESCRIPTOR WlApplicationDesktopSecurityDescriptor;
PSECURITY_DESCRIPTOR WlWinlogonDesktopSecurityDescriptor;
PSECURITY_DESCRIPTOR WlScreenSaverDesktopSecurityDescriptor;
BOOL ret = FALSE;
if (!CreateWinstaSecurity(&WlWinstaSecurityDescriptor))
{
ERR("WL: Failed to create winsta security!\n");
return ret;
}
WinstaSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
WinstaSecurity.lpSecurityDescriptor = WlWinstaSecurityDescriptor;
WinstaSecurity.bInheritHandle = TRUE;
if (!CreateApplicationDesktopSecurity(&WlApplicationDesktopSecurityDescriptor))
{
ERR("WL: Failed to create application desktop security!\n");
goto cleanup;
}
ApplicationDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
ApplicationDesktopSecurity.lpSecurityDescriptor = WlApplicationDesktopSecurityDescriptor;
ApplicationDesktopSecurity.bInheritHandle = TRUE;
if (!CreateWinlogonDesktopSecurity(&WlWinlogonDesktopSecurityDescriptor))
{
ERR("WL: Failed to create winlogon desktop security!\n");
goto cleanup;
}
WinlogonDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
WinlogonDesktopSecurity.lpSecurityDescriptor = WlWinlogonDesktopSecurityDescriptor;
WinlogonDesktopSecurity.bInheritHandle = FALSE;
if (!CreateScreenSaverSecurity(&WlScreenSaverDesktopSecurityDescriptor))
{
ERR("WL: Failed to create winlogon desktop security!\n");
goto cleanup;
}
ScreenSaverDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
ScreenSaverDesktopSecurity.lpSecurityDescriptor = WlScreenSaverDesktopSecurityDescriptor;
ScreenSaverDesktopSecurity.bInheritHandle = TRUE;
/*
* Create the interactive window station
*/
Session->InteractiveWindowStationName = L"WinSta0";
Session->InteractiveWindowStation = CreateWindowStationW(
Session->InteractiveWindowStationName,
0,
MAXIMUM_ALLOWED,
&WinstaSecurity);
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,
&ApplicationDesktopSecurity);
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,
&WinlogonDesktopSecurity);
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,
&ScreenSaverDesktopSecurity);
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;
}
if (WlWinstaSecurityDescriptor)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, WlWinstaSecurityDescriptor);
}
if (WlApplicationDesktopSecurityDescriptor)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, WlApplicationDesktopSecurityDescriptor);
}
if (WlWinlogonDesktopSecurityDescriptor)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, WlWinlogonDesktopSecurityDescriptor);
}
if (WlScreenSaverDesktopSecurityDescriptor)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, WlScreenSaverDesktopSecurityDescriptor);
}
}
return ret;
}