mirror of https://github.com/lianthony/NT4.0
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
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 );
|
|
}
|