Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1203 lines
27 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: wlxutil.c
//
// Contents: WLX helper functions
//
// Classes:
//
// Functions:
//
// History: 8-24-94 RichardW Created
//
//----------------------------------------------------------------------------
#include "precomp.h"
#pragma hdrstop
#if DBG
char * StateNames[] = {"Preload", "Initialize", "NoOne", "NoOne_Display",
"NoOne_SAS", "LoggedOnUser_StartShell", "LoggedOnUser",
"LoggedOn_SAS", "Locked", "Locked_Display", "Locked_SAS",
"WaitForLogoff", "WaitForShutdown", "Shutdown" };
#endif
WLX_DISPATCH_VERSION_1_1 WlxDispatchTable = {
WlxUseCtrlAltDel,
WlxSetContextPointer,
WlxSasNotify,
WlxSetTimeout,
WlxAssignShellProtection,
WlxMessageBox,
WlxDialogBox,
WlxDialogBoxParam,
WlxDialogBoxIndirect,
WlxDialogBoxIndirectParam,
WlxSwitchDesktopToUser,
WlxSwitchDesktopToWinlogon,
WlxChangePasswordNotify,
WlxGetSourceDesktop,
WlxSetReturnDesktop,
WlxCreateUserDesktop,
WlxChangePasswordNotifyEx };
typedef struct _WindowMapper {
DWORD fMapper;
HWND hWnd;
DLGPROC DlgProc;
struct _WindowMapper * pPrev;
LPARAM InitialParameter;
} WindowMapper, * PWindowMapper;
#define MAPPERFLAG_ACTIVE 1
#define MAPPERFLAG_DIALOG 2
#define MAPPERFLAG_SAS 4
#define MAPPERFLAG_WINLOGON 8
#define MAX_WINDOW_MAPPERS 32
WindowMapper Mappers[MAX_WINDOW_MAPPERS];
DWORD cActiveWindow;
DWORD PendingSasEvents[MAX_WINDOW_MAPPERS];
DWORD PendingSasHead;
DWORD PendingSasTail;
void
InitWindowMappers()
{
ZeroMemory(Mappers, sizeof(WindowMapper) * MAX_WINDOW_MAPPERS);
cActiveWindow = 0;
PendingSasHead = 0;
PendingSasTail = 0;
}
PWindowMapper
LocateTopMappedWindow(void)
{
int i;
for (i = 0; i < MAX_WINDOW_MAPPERS ; i++ )
{
if (Mappers[i].fMapper & MAPPERFLAG_SAS)
{
return(&Mappers[i]);
}
}
return(NULL);
}
PWindowMapper
AllocWindowMapper(void)
{
int i;
PWindowMapper pMap;
for (i = 0 ; i < MAX_WINDOW_MAPPERS ; i++ )
{
if ((Mappers[i].fMapper & MAPPERFLAG_ACTIVE) == 0)
{
cActiveWindow ++;
pMap = LocateTopMappedWindow();
if (pMap)
{
FLAG_OFF(pMap->fMapper, MAPPERFLAG_SAS);
}
Mappers[i].hWnd = NULL;
FLAG_ON(Mappers[i].fMapper, MAPPERFLAG_ACTIVE | MAPPERFLAG_SAS);
Mappers[i].pPrev = pMap;
return(&Mappers[i]);
}
}
return(NULL);
}
PWindowMapper
LocateWindowMapper(HWND hWnd)
{
int i;
for (i = 0; i < MAX_WINDOW_MAPPERS ; i++ )
{
if (Mappers[i].hWnd == hWnd)
{
return(&Mappers[i]);
}
}
return(NULL);
}
void
FreeWindowMapper(PWindowMapper pMap)
{
pMap->hWnd = NULL;
pMap->DlgProc = NULL;
if (pMap->fMapper & MAPPERFLAG_SAS)
{
if (pMap->pPrev)
{
FLAG_ON(pMap->pPrev->fMapper, MAPPERFLAG_SAS);
}
}
pMap->fMapper = 0;
pMap->pPrev = NULL;
cActiveWindow--;
}
HWND
LocateTopWindow(VOID)
{
PWindowMapper pMap;
pMap = LocateTopMappedWindow();
if (pMap)
{
return(pMap->hWnd);
}
return(NULL);
}
BOOL
SetMapperFlag(
HWND hWnd,
DWORD Flag
)
{
PWindowMapper pMap;
pMap = LocateWindowMapper(hWnd);
if (!pMap)
{
return(FALSE);
}
pMap->fMapper |= Flag;
return(TRUE);
}
BOOL
QueueSasEvent(
DWORD dwSasType)
{
if (((PendingSasTail + 1) % MAX_WINDOW_MAPPERS) == PendingSasHead)
{
return(FALSE);
}
PendingSasEvents[PendingSasTail] = dwSasType;
PendingSasTail ++;
PendingSasTail %= MAX_WINDOW_MAPPERS;
return(TRUE);
}
BOOL
FetchPendingSas(
PDWORD pSasType)
{
if (PendingSasHead == PendingSasTail)
{
return(FALSE);
}
*pSasType = PendingSasEvents[PendingSasHead++];
PendingSasHead %= MAX_WINDOW_MAPPERS;
return(TRUE);
}
BOOL
TestPendingSas(VOID)
{
return (PendingSasHead == PendingSasTail);
}
VOID
EnableSasMessages(HWND hWnd)
{
DWORD SasType;
SasMessages = TRUE;
while (FetchPendingSas(&SasType))
{
if (hWnd)
{
#if DBG
DebugLog((DEB_TRACE, "Posting queued Sas %d to window %x\n",
SasType, hWnd ));
#endif
PostMessage(hWnd, WLX_WM_SAS, (WPARAM) SasType, 0);
}
}
}
//+---------------------------------------------------------------------------
//
// Function: RootWndProc
//
// Synopsis: This is the base window proc for all testgina windows.
//
// Arguments: [hWnd] --
// [Message] --
// [wParam] --
// [lParam] --
//
// History: 7-18-94 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL
CALLBACK
RootDlgProc(
HWND hWnd,
UINT Message,
WPARAM wParam,
LPARAM lParam)
{
PWindowMapper pMap;
int res;
BOOLEAN bRet;
//
// If this is a WM_INITDIALOG message, then the parameter is the mapping,
// which needs to have a hwnd associated with it. Otherwise, do the normal
// preprocessing.
//
if (Message == WM_INITDIALOG)
{
pMap = (PWindowMapper) lParam;
pMap->hWnd = hWnd;
SetTopTimeout(hWnd);
lParam = pMap->InitialParameter;
//
// Now that everything is done, enable sas messages again. This
// protects us from people pounding on the c-a-d keys, when our response
// time is slow, e.g. due to stress. We also drain the queue of pending
// SAS events.
//
EnableSasMessages(hWnd);
}
else
{
pMap = LocateWindowMapper(hWnd);
if (!pMap)
{
return(FALSE);
}
}
if (Message == WLX_WM_SAS &&
((pMap->fMapper & MAPPERFLAG_WINLOGON) == 0))
{
if ((wParam == WLX_SAS_TYPE_TIMEOUT) ||
(wParam == WLX_SAS_TYPE_SCRNSVR_TIMEOUT) )
{
DebugLog((DEB_TRACE, "Sending timeout to top window.\n"));
}
}
bRet = pMap->DlgProc(hWnd, Message, wParam, lParam);
if (!bRet)
{
if (Message == WM_INITDIALOG)
{
return(bRet);
}
if (Message == WLX_WM_SAS)
{
if ((pMap->fMapper & MAPPERFLAG_WINLOGON) == 0)
{
//
// Re-enable the messages
EnableSasMessages(pMap->hWnd);
}
switch (wParam)
{
case WLX_SAS_TYPE_CTRL_ALT_DEL:
default:
res = WLX_DLG_SAS;
break;
case WLX_SAS_TYPE_TIMEOUT:
res = WLX_DLG_INPUT_TIMEOUT;
break;
case WLX_SAS_TYPE_SCRNSVR_TIMEOUT:
res = WLX_DLG_SCREEN_SAVER_TIMEOUT;
break;
case WLX_SAS_TYPE_USER_LOGOFF:
res = WLX_DLG_USER_LOGOFF;
break;
}
if (res)
{
EndDialog(hWnd, res);
bRet = TRUE;
}
}
}
else
{
if (Message == WLX_WM_SAS &&
((pMap->fMapper & MAPPERFLAG_WINLOGON) == 0))
{
//
// Re-enable the messages
//
EnableSasMessages(pMap->hWnd);
switch (wParam)
{
case WLX_SAS_TYPE_TIMEOUT:
res = WLX_DLG_INPUT_TIMEOUT;
break;
case WLX_SAS_TYPE_SCRNSVR_TIMEOUT:
res = WLX_DLG_SCREEN_SAVER_TIMEOUT;
break;
case WLX_SAS_TYPE_USER_LOGOFF:
res = WLX_DLG_USER_LOGOFF;
break;
default:
res = 0;
break;
}
if (res)
{
DebugLog((DEB_TRACE, "Gina ate the SAS (%d) message, but ending it anyway.\n", wParam));
EndDialog(hWnd, res);
}
}
}
return(bRet);
}
VOID
ChangeStateForSAS(PGLOBALS pGlobals)
{
#if DBG
WinstaState State = pGlobals->WinlogonState;
#endif
if ((pGlobals->SasType == WLX_SAS_TYPE_SCRNSVR_TIMEOUT) &&
(pGlobals->SasType == WLX_SAS_TYPE_TIMEOUT) )
{
DebugLog((DEB_TRACE, "SAS was a timeout, no state change\n"));
return;
}
switch (pGlobals->WinlogonState)
{
case Winsta_NoOne:
case Winsta_NoOne_Display:
pGlobals->WinlogonState = Winsta_NoOne_SAS;
break;
case Winsta_Locked:
case Winsta_Locked_Display:
pGlobals->WinlogonState = Winsta_Locked_SAS;
break;
case Winsta_LoggedOnUser:
case Winsta_LoggedOnUser_StartShell:
pGlobals->WinlogonState = Winsta_LoggedOn_SAS;
break;
case Winsta_WaitForLogoff:
case Winsta_WaitForShutdown:
case Winsta_InShutdownDlg:
break;
default:
DebugLog((DEB_ERROR, "Don't know how to get to next state from %d, %s\n",
pGlobals->WinlogonState, GetState(pGlobals->WinlogonState)));
}
#if DBG
DebugLog((DEB_TRACE, "ChangeStateForSAS: Went from %d (%s) to %d (%s)\n",
State, GetState(State), pGlobals->WinlogonState,
GetState(pGlobals->WinlogonState) ));
#endif
}
BOOL
SendSasToTopWindow(
PGLOBALS pGlobals,
DWORD SasType)
{
PWindowMapper pMap;
#if DBG
WCHAR WindowName[32];
#endif
if (cActiveWindow)
{
if ((pGlobals->WinlogonState == Winsta_InShutdownDlg) &&
(SasType == WLX_SAS_TYPE_SCRNSVR_TIMEOUT))
{
return(TRUE);
}
pMap = LocateTopMappedWindow();
if (!pMap)
{
return(FALSE);
}
if ( ( SasType > WLX_SAS_TYPE_MAX_MSFT_VALUE) ||
( SasType == WLX_SAS_TYPE_SCRNSVR_TIMEOUT) ||
( SasType == WLX_SAS_TYPE_TIMEOUT) )
{
//
// Either a timeout (which we have to forward), or a private
// which we have to forward. Kill any message boxes
//
if (KillMessageBox( SasType ))
{
DebugLog((DEB_TRACE, "Killed a pending message box\n"));
}
}
#if DBG
GetWindowText( pMap->hWnd, WindowName, 32 );
DebugLog((DEB_TRACE, "Sending SAS code %d to window %x (%ws) \n", SasType, pMap->hWnd, WindowName ));
#endif
PostMessage(pMap->hWnd, WLX_WM_SAS, (WPARAM) SasType, 0);
//
// This will cause them to be queued, and then handled later.
//
DisableSasMessages();
return(TRUE);
}
return(FALSE);
}
VOID
DestroyMprInfo(
PWLX_MPR_NOTIFY_INFO pMprInfo)
{
if (pMprInfo->pszUserName)
{
LocalFree(pMprInfo->pszUserName);
}
if (pMprInfo->pszDomain)
{
LocalFree(pMprInfo->pszDomain);
}
if (pMprInfo->pszPassword)
{
ZeroMemory(pMprInfo->pszPassword, wcslen(pMprInfo->pszPassword) * 2);
LocalFree(pMprInfo->pszPassword);
}
if (pMprInfo->pszOldPassword)
{
ZeroMemory(pMprInfo->pszOldPassword, wcslen(pMprInfo->pszOldPassword) * 2);
LocalFree(pMprInfo->pszOldPassword);
}
}
VOID
WINAPI
WlxUseCtrlAltDel(
HANDLE hWlx)
{
PGLOBALS pGlobals;
if (pGlobals = VerifyHandle(hWlx))
{
pGlobals->ForwardCAD = TRUE;
}
}
VOID
WINAPI
WlxSetContextPointer(
HANDLE hWlx,
PVOID pWlxContext
)
{
PGLOBALS pGlobals;
if (pGlobals = VerifyHandle(hWlx))
{
pGlobals->pGina->pGinaContext = pWlxContext;
}
}
VOID
WINAPI
WlxSasNotify(
HANDLE hWlx,
DWORD SasType
)
{
PGLOBALS pGlobals;
if (pGlobals = VerifyHandle(hWlx))
{
switch (SasType)
{
case WLX_SAS_TYPE_USER_LOGOFF:
case WLX_SAS_TYPE_TIMEOUT:
case WLX_SAS_TYPE_SCRNSVR_TIMEOUT:
DebugLog((DEB_ERROR, "Illegal SAS Type (%d) passed to WlxSasNotify\n", SasType ));
return;
default:
SASRouter(pGlobals, SasType);
}
}
}
BOOL
WINAPI
WlxSetTimeout(
HANDLE hWlx,
DWORD Timeout
)
{
PGLOBALS pGlobals;
if (pGlobals = VerifyHandle(hWlx))
{
if ((pGlobals->WinlogonState == Winsta_NoOne_Display) ||
(pGlobals->WinlogonState == Winsta_Locked_Display) )
{
if (Timeout)
{
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return(FALSE);
}
}
pGlobals->pGina->cTimeout = Timeout;
TimeoutUpdateTopTimeout( Timeout );
return(TRUE);
}
SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);
return(FALSE);
}
int
WINAPI
WlxAssignShellProtection(
HANDLE hWlx,
HANDLE hToken,
HANDLE hProcess,
HANDLE hThread
)
{
PGLOBALS pGlobals;
PTOKEN_DEFAULT_DACL pDefDacl;
DWORD cDefDacl = 0;
NTSTATUS Status;
PSECURITY_DESCRIPTOR psd;
unsigned char buf[SECURITY_DESCRIPTOR_MIN_LENGTH];
BOOL Success;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
return(ERROR_INVALID_HANDLE);
}
Status = NtQueryInformationToken(hToken, TokenDefaultDacl, NULL, 0, &cDefDacl);
if (!NT_SUCCESS(Status) && ( Status != STATUS_BUFFER_TOO_SMALL ))
{
return(RtlNtStatusToDosError(Status));
}
pDefDacl = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cDefDacl);
if (!pDefDacl)
{
return(ERROR_OUTOFMEMORY);
}
Status = NtQueryInformationToken(hToken, TokenDefaultDacl,
pDefDacl, cDefDacl, &cDefDacl);
if (!NT_SUCCESS(Status))
{
LocalFree(pDefDacl);
return(RtlNtStatusToDosError(Status));
}
psd = (PSECURITY_DESCRIPTOR) buf;
InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(psd, TRUE, pDefDacl->DefaultDacl, FALSE);
Success = SetKernelObjectSecurity(hProcess, DACL_SECURITY_INFORMATION, psd);
LocalFree(pDefDacl);
if (Success)
{
if (SetProcessToken(pGlobals, hProcess, hThread, hToken))
return(0);
}
return(GetLastError());
}
int WINAPI
WlxMessageBox(
HANDLE hWlx,
HWND hWnd,
LPWSTR lpsz1,
LPWSTR lpsz2,
UINT fmb)
{
PGLOBALS pGlobals;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);
return(-1);
}
return(TimeoutMessageBoxlpstr(pGlobals, hWnd, lpsz1, lpsz2, fmb,
pGlobals->pGina->cTimeout | TIMEOUT_SS_NOTIFY ) );
}
int WINAPI
WlxDialogBox(
HANDLE hWlx,
HANDLE hInstance,
LPWSTR lpsz1,
HWND hWnd,
DLGPROC dlgproc)
{
return(WlxDialogBoxParam(hWlx, hInstance, lpsz1, hWnd, dlgproc, 0));
}
int WINAPI
WlxDialogBoxIndirect(
HANDLE hWlx,
HANDLE hInstance,
LPCDLGTEMPLATE lpTemplate,
HWND hWnd,
DLGPROC dlgproc)
{
return(WlxDialogBoxIndirectParam(hWlx, hInstance, lpTemplate, hWnd, dlgproc, 0));
}
int WINAPI
WlxDialogBoxParam(
HANDLE hWlx,
HANDLE hInstance,
LPWSTR lpsz1,
HWND hWnd,
DLGPROC dlgproc,
LPARAM lParam)
{
PWindowMapper pMap;
PGLOBALS pGlobals;
int res;
pMap = AllocWindowMapper();
if (!pMap)
{
ASSERTMSG("Too many nested windows? send mail to richardw", pMap);
DebugLog((DEB_ERROR, "Too many nested windows?!?\n"));
SetLastError(ERROR_OUTOFMEMORY);
return(-1);
}
pMap->InitialParameter = lParam;
pMap->DlgProc = dlgproc;
pMap->fMapper |= MAPPERFLAG_DIALOG;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);
return(-1);
}
//res = DialogBoxParam(hInstance, lpsz1, hWnd, RootDlgProc, (LPARAM) pMap);
res = TimeoutDialogBoxParam(pGlobals, hInstance, lpsz1, hWnd,
RootDlgProc, (LPARAM) pMap,
pGlobals->pGina->cTimeout | TIMEOUT_SS_NOTIFY);
FreeWindowMapper(pMap);
return(res);
}
int WINAPI
WlxDialogBoxIndirectParam(
HANDLE hWlx,
HANDLE hInstance,
LPCDLGTEMPLATE lpTemplate,
HWND hWnd,
DLGPROC dlgproc,
LPARAM lParam)
{
PWindowMapper pMap;
int res;
pMap = AllocWindowMapper();
if (!pMap)
{
ASSERTMSG("Too many nested windows? send mail to richardw", pMap);
DebugLog((DEB_ERROR, "Too many nested windows?!?\n"));
SetLastError(ERROR_OUTOFMEMORY);
return(-1);
}
pMap->InitialParameter = lParam;
pMap->DlgProc = dlgproc;
pMap->fMapper |= MAPPERFLAG_DIALOG;
res = DialogBoxIndirectParam(hInstance, lpTemplate, hWnd, RootDlgProc, (LPARAM) pMap);
FreeWindowMapper(pMap);
return(res);
}
int WINAPI
WlxSwitchDesktopToUser(
HANDLE hWlx)
{
PGLOBALS pGlobals;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
return(ERROR_INVALID_HANDLE);
}
SetActiveDesktop(&pGlobals->WindowStation, Desktop_Application);
SetThreadDesktop(pGlobals->WindowStation.hdeskApplication);
return(0);
}
int WINAPI
WlxSwitchDesktopToWinlogon(
HANDLE hWlx)
{
PGLOBALS pGlobals;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
return(ERROR_INVALID_HANDLE);
}
SetActiveDesktop(&pGlobals->WindowStation, Desktop_Winlogon);
SetThreadDesktop(pGlobals->WindowStation.hdeskWinlogon);
return(0);
}
int WINAPI
WlxChangePasswordNotify(
HANDLE hWlx,
PWLX_MPR_NOTIFY_INFO pMprInfo,
DWORD dwChangeInfo)
{
PGLOBALS pGlobals;
int Result;
return WlxChangePasswordNotifyEx( hWlx, pMprInfo, dwChangeInfo, NULL, NULL );
}
int WINAPI
WlxChangePasswordNotifyEx(
HANDLE hWlx,
PWLX_MPR_NOTIFY_INFO pMprInfo,
DWORD dwChangeInfo,
PWSTR pszProvider,
PVOID pvReserved)
{
PGLOBALS pGlobals;
int Result;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
return(ERROR_INVALID_HANDLE);
}
Result = MprChangePasswordNotify(
pGlobals,
LocateTopWindow(),
pszProvider,
pMprInfo->pszUserName,
pMprInfo->pszDomain,
pMprInfo->pszPassword,
pMprInfo->pszOldPassword,
dwChangeInfo,
FALSE);
DestroyMprInfo(pMprInfo);
if (Result == DLG_SUCCESS)
{
return(0);
}
else
return(ERROR_INVALID_PARAMETER);
}
BOOL
WINAPI
WlxGetSourceDesktop(
HANDLE hWlx,
PWLX_DESKTOP * ppDesktop)
{
PGLOBALS pGlobals;
DWORD len;
PWLX_DESKTOP pDesktop;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
SetLastError(ERROR_INVALID_HANDLE);
return( FALSE );
}
if (pGlobals->WindowStation.pszDesktop)
{
len = (wcslen(pGlobals->WindowStation.pszDesktop) + 1) * sizeof(WCHAR);
}
else
{
len = 0;
}
pDesktop = LocalAlloc( LMEM_FIXED, sizeof(WLX_DESKTOP) + len );
if (!pDesktop)
{
return( FALSE );
}
pDesktop->Size = sizeof(WLX_DESKTOP);
pDesktop->Flags = WLX_DESKTOP_NAME;
pDesktop->hDesktop = NULL;
pDesktop->pszDesktopName = (PWSTR) (pDesktop + 1);
if (len)
{
wcscpy( pDesktop->pszDesktopName, pGlobals->WindowStation.pszDesktop );
}
*ppDesktop = pDesktop;
return( TRUE );
}
BOOL
WINAPI
WlxSetReturnDesktop(
HANDLE hWlx,
PWLX_DESKTOP pDesktop)
{
PGLOBALS pGlobals;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
SetLastError(ERROR_INVALID_HANDLE);
return( FALSE );
}
if ((pDesktop->Size != sizeof(WLX_DESKTOP)) ||
((pDesktop->Flags & (WLX_DESKTOP_HANDLE | WLX_DESKTOP_NAME)) == 0) )
{
DebugLog((DEB_ERROR, "Invalid desktop\n"));
SetLastError( ERROR_INVALID_PARAMETER );
return( FALSE );
}
return( SetReturnDesktop( &pGlobals->WindowStation, pDesktop ) );
}
BOOL
WINAPI
WlxCreateUserDesktop(
HANDLE hWlx,
HANDLE hToken,
DWORD Flags,
PWSTR pszDesktopName,
PWLX_DESKTOP * ppDesktop)
{
PGLOBALS pGlobals;
PTOKEN_GROUPS pGroups;
PTOKEN_USER pUser;
DWORD Needed;
NTSTATUS Status;
DWORD i;
PSID pSid;
PWLX_DESKTOP pDesktop;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
SetLastError(ERROR_INVALID_HANDLE);
return( FALSE );
}
if (((Flags & (WLX_CREATE_INSTANCE_ONLY | WLX_CREATE_USER)) == 0 ) ||
((Flags & (WLX_CREATE_INSTANCE_ONLY | WLX_CREATE_USER)) ==
(WLX_CREATE_INSTANCE_ONLY | WLX_CREATE_USER) ) )
{
DebugLog((DEB_ERROR, "Invalid flags\n"));
SetLastError( ERROR_INVALID_PARAMETER );
return( FALSE );
}
pGroups = NULL;
pUser = NULL;
pSid = NULL;
if ( Flags & WLX_CREATE_INSTANCE_ONLY )
{
Status = NtQueryInformationToken( hToken,
TokenGroups,
NULL,
0,
&Needed );
if ( Status != STATUS_BUFFER_TOO_SMALL )
{
SetLastError( RtlNtStatusToDosError( Status ) );
return( FALSE );
}
pGroups = (PTOKEN_GROUPS) LocalAlloc( LMEM_FIXED, Needed );
if ( !pGroups )
{
return( FALSE );
}
Status = NtQueryInformationToken( hToken,
TokenGroups,
pGroups,
Needed,
&Needed );
if ( !NT_SUCCESS( Status ) )
{
LocalFree( pGroups );
SetLastError( RtlNtStatusToDosError( Status ) );
return( FALSE );
}
for (i = 0 ; i < pGroups->GroupCount ; i++ )
{
if ( pGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID )
{
pSid = pGroups->Groups[i].Sid;
break;
}
}
}
else
{
Status = NtQueryInformationToken( hToken,
TokenUser,
NULL,
0,
&Needed );
if ( Status != STATUS_BUFFER_TOO_SMALL )
{
SetLastError( RtlNtStatusToDosError( Status ) );
return( FALSE );
}
pUser = (PTOKEN_USER) LocalAlloc( LMEM_FIXED, Needed );
if ( !pUser )
{
return( FALSE );
}
Status = NtQueryInformationToken( hToken,
TokenUser,
pUser,
Needed,
&Needed );
if ( !NT_SUCCESS( Status ) )
{
LocalFree( pUser );
SetLastError( RtlNtStatusToDosError( Status ) );
return( FALSE );
}
pSid = pUser->User.Sid;
}
if ( !pSid )
{
SetLastError( ERROR_INVALID_PARAMETER );
goto CleanUp;
}
//
// Okay, we have the right SID now, so create the desktop.
//
Needed = sizeof( WLX_DESKTOP ) + (wcslen( pszDesktopName ) + 1 ) * sizeof(WCHAR);
pDesktop = (PWLX_DESKTOP) LocalAlloc( LMEM_FIXED, Needed );
if ( !pDesktop )
{
goto CleanUp;
}
pDesktop->Size = sizeof( WLX_DESKTOP );
pDesktop->Flags = WLX_DESKTOP_NAME;
pDesktop->hDesktop = NULL;
pDesktop->pszDesktopName = (PWSTR) (pDesktop + 1);
wcscpy( pDesktop->pszDesktopName, pszDesktopName );
pDesktop->hDesktop = CreateDesktop( pszDesktopName,
NULL, NULL, 0, MAXIMUM_ALLOWED, NULL);
if ( !pDesktop->hDesktop )
{
goto CleanUp;
}
if (!SetUserDesktopSecurity(pDesktop->hDesktop,
pSid, pWinlogonSid ) )
{
goto CleanUp;
}
if (!AddUserToWinsta( &pGlobals->WindowStation,
pSid,
hToken ) )
{
goto CleanUp;
}
*ppDesktop = pDesktop;
pDesktop->Flags |= WLX_DESKTOP_HANDLE;
if ( pGroups )
{
LocalFree( pGroups );
}
if ( pUser )
{
LocalFree( pUser );
}
return( TRUE );
CleanUp:
if ( pDesktop )
{
if ( pDesktop->hDesktop )
{
CloseDesktop( pDesktop->hDesktop );
}
LocalFree( pDesktop );
}
if ( pGroups )
{
LocalFree( pGroups );
}
if ( pUser )
{
LocalFree( pUser );
}
return( FALSE );
}
BOOL
WINAPI
WlxCloseUserDesktop(
HANDLE hWlx,
PWLX_DESKTOP pDesktop,
HANDLE hToken )
{
PGLOBALS pGlobals;
if (!(pGlobals = VerifyHandle(hWlx)))
{
DebugLog((DEB_ERROR, "Invalid hWlx handle\n"));
SetLastError(ERROR_INVALID_HANDLE);
return( FALSE );
}
if ( RemoveUserFromWinsta( &pGlobals->WindowStation, hToken ) )
{
return( CloseDesktop( pDesktop->hDesktop ) );
}
return( FALSE );
}