windows-nt/Source/XPSP1/NT/ds/security/gina/testgina/testgina.c
2020-09-26 16:20:57 +08:00

768 lines
20 KiB
C

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: msgina.c
//
// Contents: Microsoft Logon GUI DLL
//
// History: 7-14-94 RichardW Created
//
//----------------------------------------------------------------------------
#include "testgina.h"
#include <stdio.h>
#include <wchar.h>
HINSTANCE hDllInstance; // Dll instance,
DWORD DllVersion; // Dll Version
HINSTANCE hAppInstance; // App instance, for dialogs, etc.
HWND hMainWindow; // Main window
WNDCLASS WndClass; // Window class
HICON hIcon;
WNDCLASS StatusClass; // Status Window class
HWND hStatusWindow; // Status Window
HMENU hDebugMenu; // Debug Menu
USER_SAS UserDefSas[MAX_USER_SASES];
DWORD UserSases;
DWORD CurrentDesktop;
PWLX_DESKTOP Desktops[ MAX_DESKTOPS ];
DWORD DesktopCount;
DWORD OtherDesktop;
LRESULT StatusProc(HWND, UINT, WPARAM, LPARAM);
WLX_DISPATCH_VERSION_1_3 WlxDispatchTable = {
WlxUseCtrlAltDel,
WlxSetContextPointer,
WlxSasNotify,
WlxSetTimeout,
WlxAssignShellProtection,
WlxMessageBox,
WlxDialogBox,
WlxDialogBoxParam,
WlxDialogBoxIndirect,
WlxDialogBoxIndirectParam,
WlxSwitchDesktopToUser,
WlxSwitchDesktopToWinlogon,
WlxChangePasswordNotify,
WlxGetSourceDesktop,
WlxSetReturnDesktop,
WlxCreateUserDesktop,
WlxChangePasswordNotifyEx,
WlxCloseUserDesktop,
WlxSetOption,
WlxGetOption,
WlxWin31Migrate,
WlxQueryClientCredentials,
WlxQueryICCredentials,
WlxDisconnect };
PWLX_NEGOTIATE pWlxNegotiate;
PWLX_INITIALIZE pWlxInitialize;
PWLX_DISPLAYSASNOTICE pWlxDisplaySASNotice;
PWLX_LOGGEDOUTSAS pWlxLoggedOutSAS;
PWLX_ACTIVATEUSERSHELL pWlxActivateUserShell;
PWLX_LOGGEDONSAS pWlxLoggedOnSAS;
PWLX_DISPLAYLOCKEDNOTICE pWlxDisplayLockedNotice;
PWLX_WKSTALOCKEDSAS pWlxWkstaLockedSAS;
PWLX_LOGOFF pWlxLogoff;
PWLX_SHUTDOWN pWlxShutdown;
WinstaState GinaState; // State of the GinaTest
DWORD fTestGina; // Flags
DWORD GinaBreakFlags; // Break points for Gina debugging
WCHAR szGinaDll[MAX_PATH]; // Path and name of the DLL
DWORD SizeX, SizeY;
DWORD PosX, PosY;
DWORD StatusHeight = 24;
DWORD StatusDeltaX;
DWORD StatusDeltaY;
DWORD LastRetCode;
BOOL LastBoolRet;
PWSTR szErrorMessages[] = { TEXT("Internal TestGina Error!"),
TEXT("Invalid hWlx Handle Passed"),
TEXT("Improper SAS supplied"),
TEXT("Invalid Protocol Level"),
TEXT("Load of DLL Failed"),
TEXT("Missing Function"),
TEXT("Unknown HWND"),
TEXT("No Window for SAS message"),
TEXT("Invalid SAS code in message"),
TEXT("Invalid return code from function")
};
PWSTR szStates[] = { TEXT("Pre Load"),
TEXT("Initialize"),
TEXT("No One Logged On"),
TEXT("No One Logged On -- Display Notice"),
TEXT("No One Logged On -- SAS Received"),
TEXT("User Logged On -- Start Shell"),
TEXT("User Logged On"),
TEXT("User Logged On -- SAS Received"),
TEXT("Wksta Locked"),
TEXT("Wksta Locked -- SAS Received"),
TEXT("Waiting to Shutdown"),
TEXT("Shutdown")
};
PWSTR szRetcodes[] = { TEXT("N/A"),
TEXT("WLX_SAS_ACTION_USER_LOGON"),
TEXT("WLX_SAS_ACTION_NONE"),
TEXT("WLX_SAS_ACTION_LOCK_WKSTA"),
TEXT("WLX_SAS_ACTION_LOGOFF"),
TEXT("WLX_SAS_ACTION_SHUTDOWN"),
TEXT("WLX_SAS_ACTION_PWD_CHANGED"),
TEXT("WLX_SAS_ACTION_TASKLIST"),
TEXT("WLX_SAS_ACTION_UNLOCK_WKSTA"),
TEXT("WLX_SAS_ACTION_FORCE_LOGOFF"),
TEXT("WLX_SAS_ACTION_SHUTDOWN_POWER_OFF"),
TEXT("WLX_SAS_ACTION_SHUTDOWN_REBOOT")
};
BOOLEAN
AmIBeingDebugged(void)
{
HANDLE DebugPort;
NTSTATUS Status;
DebugPort = (HANDLE) NULL;
Status = NtQueryInformationProcess(
NtCurrentProcess(),
ProcessDebugPort,
(PVOID) &DebugPort,
sizeof(DebugPort),
NULL );
if (NT_SUCCESS(Status) && DebugPort)
{
return(TRUE);
}
return(FALSE);
}
void
TestGinaError( DWORD dwError,
PWSTR pszFunction)
{
int mbret;
BOOLEAN fDbg;
WCHAR szBuffer[MAX_PATH];
WCHAR szCaption[MAX_PATH];
if (dwError > (sizeof(szErrorMessages) / sizeof(PWSTR)))
{
dwError = 0;
}
fDbg = AmIBeingDebugged();
wsprintf(szCaption, TEXT("%ws: Error %d"), pszFunction, dwError);
if (fDbg)
{
wsprintf(szBuffer, TEXT("The following error occurred:\n%ws\nPress OK to exit, Cancel to debug"),
szErrorMessages[dwError]);
}
else
wsprintf(szBuffer, TEXT("The following error occurred:\n%ws\nPress OK to exit."),
szErrorMessages[dwError]);
mbret = MessageBox( hMainWindow,
szBuffer,
szCaption,
MB_ICONSTOP | (fDbg ? MB_OKCANCEL : MB_OK) );
if (fDbg && (mbret == IDCANCEL))
{
DbgBreakPoint();
mbret = MessageBox(hMainWindow, TEXT("Continue after error?"),
TEXT("TestGina"), MB_OKCANCEL);
if (mbret == IDOK)
{
return;
}
}
ExitProcess(dwError);
}
void
DoClass(void)
{
WndClass.style = 0;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hAppInstance;
WndClass.hIcon = LoadIcon(hAppInstance, MAKEINTRESOURCE(TESTGINAICON));
hIcon = WndClass.hIcon;
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
WndClass.lpszMenuName = MAKEINTRESOURCE(TESTGINAMENU);
WndClass.lpszClassName = TEXT("TestGina");
RegisterClass(&WndClass);
}
int
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrev,
LPSTR pszCommandLine,
int nCmdShow)
{
MSG msg;
HMENU hMenu;
hAppInstance = hInstance;
InitCommonControls();
DoClass();
SizeX = (DWORD) CW_USEDEFAULT;
SizeY = (DWORD) CW_USEDEFAULT;
PosX = (DWORD) CW_USEDEFAULT;
PosY = (DWORD) CW_USEDEFAULT;
LoadParameters();
InitializeDesktops();
hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(TESTGINAMENU));
if (szGinaDll[0] == TEXT('\0'))
{
DeleteMenu(hMenu, IDM_DLL_LOAD_LAST, MF_BYCOMMAND);
}
else
{
WCHAR tmp[32];
PWSTR pszName;
if (wcslen(szGinaDll) > 32)
{
pszName = wcsrchr(szGinaDll, TEXT('\\'));
if (!pszName)
{
wcsncpy(tmp, szGinaDll, 31);
}
else
{
wcsncpy(tmp, szGinaDll, 3);
wcscpy(tmp + 3, TEXT("..."));
wcsncpy(tmp+6, pszName, 25);
}
ModifyMenu(hMenu, IDM_DLL_LOAD_LAST, MF_BYCOMMAND | MF_STRING,
IDM_DLL_LOAD_LAST, (LPCTSTR) tmp);
}
else
{
ModifyMenu(hMenu, IDM_DLL_LOAD_LAST, MF_BYCOMMAND | MF_STRING,
IDM_DLL_LOAD_LAST, szGinaDll);
}
}
if (AmIBeingDebugged())
{
hDebugMenu = LoadMenu(hInstance, MAKEINTRESOURCE(DEBUGGINAMENU));
InsertMenu(hMenu, 3, MF_BYPOSITION | MF_POPUP, (UINT) hDebugMenu, TEXT("&Debug"));
}
hMainWindow = CreateWindow(
TEXT("TestGina"),
TEXT("TestGina"),
WS_OVERLAPPEDWINDOW,
PosX,
PosY,
SizeX,
SizeY,
NULL,
hMenu,
hInstance,
NULL);
if (!hMainWindow)
{
return(0);
}
RegisterHotKey(hMainWindow, 0, MOD_CONTROL, VK_DELETE);
RegisterHotKey(hMainWindow, 1, MOD_CONTROL, VK_ADD);
ShowWindow(hMainWindow, nCmdShow);
StatusDeltaX = GetSystemMetrics(SM_CXFRAME);
StatusDeltaY = GetSystemMetrics(SM_CYFRAME);
ShowWindow(hMainWindow, nCmdShow);
SetFocus(hMainWindow);
UpdateMenuBar();
EnableOptions(FALSE);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0 ;
}
void
UpdateGinaState(DWORD Update)
{
LogEvent( 0, "UpdateGinaState(%d): CurrentDesktop = %d, OtherDesktop = %d\n",
Update, CurrentDesktop, OtherDesktop );
switch (Update)
{
case UPDATE_INITIALIZE:
GinaState = Winsta_NoOne;
CurrentDesktop = WINLOGON_DESKTOP;
OtherDesktop = WINLOGON_DESKTOP;
break;
case UPDATE_DISPLAY_NOTICE:
if (GinaState != Winsta_NoOne)
{
TestGinaError(0, TEXT("UpdateGinaState_1"));
}
GinaState = Winsta_NoOne_Display;
CurrentDesktop = WINLOGON_DESKTOP;
OtherDesktop = WINLOGON_DESKTOP;
break;
case UPDATE_SAS_BYPASS:
//
// The kind of weird state of skipping DISPLAY and invoking the
//
if ((GinaState == Winsta_NoOne) || (GinaState == Winsta_NoOne_Display))
{
GinaState = Winsta_NoOne_SAS;
}
else if ((GinaState == Winsta_LoggedOnUser))
{
GinaState = Winsta_LoggedOn_SAS;
}
else if (GinaState == Winsta_Locked)
{
GinaState = Winsta_Locked_SAS;
}
LastRetCode = 0;
CurrentDesktop = WINLOGON_DESKTOP;
OtherDesktop = WINLOGON_DESKTOP;
break;
case UPDATE_SAS_RECEIVED:
if ((GinaState == Winsta_NoOne) || (GinaState == Winsta_NoOne_Display))
{
GinaState = Winsta_NoOne_SAS;
}
else if (GinaState == Winsta_LoggedOnUser)
{
GinaState = Winsta_LoggedOn_SAS;
}
else if (GinaState == Winsta_Locked)
{
GinaState = Winsta_Locked_SAS;
}
OtherDesktop = CurrentDesktop;
CurrentDesktop = WINLOGON_DESKTOP;
LastRetCode = 0;
break;
case UPDATE_USER_LOGON:
if (GinaState != Winsta_NoOne_SAS)
{
TestGinaError(0, TEXT("UpdateGinaState_2"));
}
GinaState = Winsta_LoggedOnUser;
OtherDesktop = WINLOGON_DESKTOP;
CurrentDesktop = DEFAULT_DESKTOP;
break;
case UPDATE_LOCK_WKSTA:
if (GinaState != Winsta_LoggedOn_SAS)
{
TestGinaError(0, TEXT("UpdateGinaState_3"));
}
GinaState = Winsta_Locked;
CurrentDesktop = WINLOGON_DESKTOP;
break;
case UPDATE_UNLOCK_WKSTA:
if (GinaState != Winsta_Locked_SAS)
{
TestGinaError(0, TEXT("UpdateGinaState_4"));
}
GinaState = Winsta_LoggedOnUser;
CurrentDesktop = OtherDesktop;
OtherDesktop = WINLOGON_DESKTOP;
break;
case UPDATE_SAS_COMPLETE:
if (GinaState == Winsta_LoggedOn_SAS)
{
GinaState = Winsta_LoggedOnUser;
CurrentDesktop = OtherDesktop;
OtherDesktop = WINLOGON_DESKTOP;
}
if (GinaState == Winsta_NoOne_SAS)
{
GinaState = Winsta_NoOne;
}
if (GinaState == Winsta_Locked_SAS)
{
GinaState = Winsta_Locked;
}
break;
case UPDATE_LOGOFF:
LastRetCode = 0;
GinaState = Winsta_NoOne;
break;
}
LogEvent( 0, "UpdateGinaState: CurrentDesktop = %d, OtherDesktop = %d\n",
CurrentDesktop, OtherDesktop );
UpdateStatusBar( );
}
void
LoadGinaSpecificParameters(
VOID )
{
PWSTR pszGina;
HKEY hKey;
HKEY hRealKey;
int err;
DWORD cbBuffer;
DWORD dwType;
WCHAR szTemp[512];
DWORD i;
PWSTR pszWalk;
DWORD RealBuf;
DWORD disp;
pszGina = wcsrchr( szGinaDll, TEXT('\\') );
if (!pszGina)
{
pszGina = szGinaDll;
}
else
{
pszGina++;
}
err = RegCreateKey( HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\TestGina"), &hKey );
if (err)
{
return;
}
err = RegCreateKeyEx( hKey,
pszGina,
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_READ | KEY_WRITE,
NULL,
&hRealKey,
&disp );
RegCloseKey( hKey );
if (err)
{
return;
}
cbBuffer = 512 * sizeof(WCHAR);
err = RegQueryValueEx( hRealKey,
TEXT("Order"),
NULL,
&dwType,
(LPBYTE) szTemp,
&cbBuffer );
if (err || (dwType != REG_MULTI_SZ))
{
RegCloseKey( hRealKey );
return;
}
pszWalk = szTemp;
for (i = 0; i < 4 ; i++ )
{
RealBuf = sizeof(DWORD);
err = RegQueryValueEx( hRealKey,
pszWalk,
NULL,
&dwType,
(LPBYTE) &UserDefSas[i].Value,
&RealBuf );
if (err || ( dwType != REG_DWORD))
{
RegCloseKey( hRealKey );
return;
}
wcsncpy( UserDefSas[i].Name, pszWalk, 128 );
pszWalk += wcslen(pszWalk) + 1;
if (*pszWalk == TEXT('\0'))
{
break;
}
}
RegCloseKey( hRealKey );
UserSases = i + 1;
}
void
SaveGinaSpecificParameters(void)
{
PWSTR pszGina;
HKEY hKey;
HKEY hRealKey;
int err;
DWORD cbBuffer;
WCHAR szTemp[512];
DWORD i;
DWORD disp;
pszGina = wcsrchr( szGinaDll, TEXT('\\') );
if (!pszGina)
{
pszGina = szGinaDll;
}
else
{
pszGina++;
}
err = RegCreateKey( HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\TestGina"), &hKey );
if (err)
{
return;
}
err = RegCreateKeyEx( hKey,
pszGina,
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_READ | KEY_WRITE,
NULL,
&hRealKey,
&disp );
RegCloseKey( hKey );
if (err)
{
return;
}
cbBuffer = 0;
for (i = 0; i < UserSases ; i++ )
{
wcscpy( &szTemp[cbBuffer],
UserDefSas[i].Name );
cbBuffer += wcslen(UserDefSas[i].Name) + 1;
}
szTemp[cbBuffer++] = TEXT('\0');
RegSetValueEx( hRealKey,
TEXT("Order"),
0,
REG_MULTI_SZ,
(LPBYTE) szTemp,
cbBuffer * 2);
for (i = 0; i < UserSases ; i++ )
{
RegSetValueEx( hRealKey,
UserDefSas[i].Name,
0,
REG_DWORD,
(LPBYTE) &UserDefSas[i].Value,
sizeof(DWORD) );
}
RegCloseKey( hRealKey );
}
void
LoadParameters(void)
{
HKEY hKey;
int err;
DWORD dwX;
DWORD cbBuffer;
DWORD dwType;
err = RegCreateKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\TestGina"), &hKey);
if (err)
{
return;
}
cbBuffer = sizeof(dwX);
err = RegQueryValueEx(hKey, TEXT("Size"), NULL, &dwType, (LPBYTE)&dwX, &cbBuffer);
if (err)
{
RegCloseKey(hKey);
return;
}
SizeX = LOWORD(dwX);
SizeY = HIWORD(dwX);
err = RegQueryValueEx(hKey, TEXT("Pos"), NULL, &dwType, (LPBYTE)&dwX, &cbBuffer);
if (err)
{
RegCloseKey(hKey);
return;
}
PosX = LOWORD(dwX);
PosY = HIWORD(dwX);
cbBuffer = sizeof(szGinaDll);
err = RegQueryValueEx(hKey, TEXT("Dll"), NULL, &dwType, (LPBYTE)szGinaDll, &cbBuffer);
RegCloseKey(hKey);
}
void
SaveParameters(void)
{
HKEY hKey;
int err;
DWORD dwX;
err = RegCreateKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\TestGina"), &hKey);
if (err)
{
return;
}
dwX = (SizeY << 16) + (SizeX & 0x0000FFFF);
err = RegSetValueEx(hKey, TEXT("Size"), 0, REG_DWORD, (LPBYTE)&dwX, sizeof(DWORD));
if (err)
{
RegCloseKey(hKey);
return;
}
dwX = (PosY << 16) + (PosX & 0x0000FFFF);
err = RegSetValueEx(hKey, TEXT("Pos"), 0, REG_DWORD, (LPBYTE)&dwX, sizeof(DWORD));
if (err)
{
RegCloseKey(hKey);
return;
}
err = RegSetValueEx(hKey, TEXT("Dll"), 0, REG_SZ, (LPBYTE) szGinaDll, (wcslen(szGinaDll) + 1) * sizeof(WCHAR));
RegCloseKey(hKey);
}
PrintStatus(HWND hWnd)
{
WCHAR szText[128];
PWSTR pszRet;
wsprintf( szText, TEXT("GINA State: %s"), szStates[ GinaState ] );
SendMessage( hStatusWindow, SB_SETTEXT, 0, (LPARAM) szText );
if ( LastRetCode == WLX_SAS_ACTION_BOOL_RET )
{
if ( LastBoolRet )
{
pszRet = TEXT("TRUE");
}
else
{
pszRet = TEXT("FALSE");
}
}
else
{
pszRet = szRetcodes[ LastRetCode ];
}
wsprintf( szText, TEXT("Last Return: %s"), pszRet );
SendMessage( hStatusWindow, SB_SETTEXT, 1, (LPARAM) szText );
wsprintf( szText, TEXT("Desktop: %s"), Desktops[ CurrentDesktop ]->pszDesktopName );
SendMessage( hStatusWindow, SB_SETTEXT, 2, (LPARAM) szText );
return(0);
}
void
UpdateStatusBar(VOID)
{
RECT rect;
int Widths[4];
GetClientRect( hStatusWindow, &rect );
rect.right -= 15; // Reduce by size grip
Widths[0] = rect.right / 3;
Widths[1] = rect.right / 3 + Widths[0] ;
Widths[2] = rect.right / 3 + Widths[1] ;
SendMessage( hStatusWindow, SB_SETPARTS, (WPARAM) 3, (LPARAM) Widths );
PrintStatus( hStatusWindow );
}