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.
 
 
 
 
 
 

582 lines
13 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
setuplgn.c
Abstract:
Routines for the special version of winlogon for Setup.
Author:
Ted Miller (tedm) 4-May-1992
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#if DEVL
BOOL bDebugSetup;
#endif
//
// Handle to the event used by lsa to stall security initialization.
//
HANDLE LsaStallEvent = NULL;
//
// Thread Id of the main thread of setuplgn.
//
DWORD MainThreadId;
DWORD
WaiterThread(
PVOID hProcess
);
VOID
CreateLsaStallEvent(
VOID
)
/*++
Routine Description:
Create the event used by lsa to stall security initialization.
Arguments:
None.
Return Value:
None.
--*/
{
OBJECT_ATTRIBUTES EventAttributes;
NTSTATUS Status;
UNICODE_STRING EventName;
HANDLE EventHandle;
RtlInitUnicodeString(&EventName,TEXT("\\INSTALLATION_SECURITY_HOLD"));
InitializeObjectAttributes(&EventAttributes,&EventName,0,0,NULL);
Status = NtCreateEvent( &EventHandle,
0,
&EventAttributes,
NotificationEvent,
FALSE
);
if(NT_SUCCESS(Status)) {
LsaStallEvent = EventHandle;
} else {
DebugLog((DEB_ERROR, "Couldn't create lsa stall event (status = %lx)",Status));
}
}
DWORD
CheckSetupType (
VOID
)
/*++
Routine Description:
See if the value "SetupType" exists under the Winlogon key in WIN.INI;
return its value. Return SETUPTYPE_NONE if not found.
Arguments:
None.
Return Value:
SETUPTYPE_xxxx (see SETUPLGN.H).
--*/
{
DWORD SetupType = SETUPTYPE_NONE ;
HANDLE KeyHandle = OpenNtRegKey(KEYNAME_SETUP) ;
if (KeyHandle) {
if ( ! ReadRegistry( KeyHandle,
VARNAME_SETUPTYPE,
REG_DWORD,
(TCHAR*) & SetupType,
& SetupType ) )
SetupType = SETUPTYPE_NONE ;
NtClose(KeyHandle);
}
return SetupType ;
}
BOOL
SetSetupType (
DWORD type
)
/*++
Routine Description:
Set the "SetupType" value in the Registry.
Arguments:
DWORD type (see SETUPLGN.H)
Return Value:
TRUE if operation successful.
--*/
{
char buffer[20];
BOOL Result = FALSE ;
HANDLE KeyHandle = OpenNtRegKey(KEYNAME_SETUP) ;
if (KeyHandle) {
sprintf(buffer,"%ld", type);
Result = WriteRegistry( KeyHandle,
VARNAME_SETUPTYPE_A,
REG_DWORD, buffer,
sizeof type );
NtClose(KeyHandle);
}
return Result ;
}
BOOL
AppendToSetupCommandLine(
LPSTR pszCommandArguments
)
/*++
Routine Description:
Append to the setup command line in the Registry.
Arguments:
LPSTR pszCommandArguments (e.g. " /t STF_COMPUTERNAME = MACHINENAME")
Return Value:
TRUE if operation successful.
--*/
{
TCHAR CmdLineBuffer[512];
DWORD DataSize;
BOOL Result = FALSE ;
HANDLE KeyHandle = OpenNtRegKey(KEYNAME_SETUP) ;
if (KeyHandle) {
DataSize = sizeof(CmdLineBuffer);
Result = ReadRegistry( KeyHandle,
VARNAME_SETUPCMD,
REG_SZ,
CmdLineBuffer,
&DataSize
);
if (Result) {
UNICODE_STRING UniString;
STRING String;
char szBuf[1024];
String.Buffer = szBuf;
String.MaximumLength = sizeof(szBuf);
RtlInitUnicodeString(&UniString, CmdLineBuffer);
RtlUnicodeStringToAnsiString(&String, &UniString, FALSE);
RtlAppendAsciizToString(&String, pszCommandArguments);
String.Buffer[ String.Length ] = '\0';
Result = WriteRegistry( KeyHandle,
VARNAME_SETUPCMD_A,
REG_SZ,
szBuf,
String.Length
);
}
NtClose(KeyHandle);
}
return Result ;
}
VOID
ExecuteSetup(
PGLOBALS pGlobals
)
/*++
Routine Description:
Execute setup.exe. The command line to be passed to setup is obtained
from HKEY_LOCAL_MACHINE\system\setup:cmdline. Wait for setup to complete
before returning.
Arguments:
pGlobals - global data structure
Return Value:
None.
--*/
{
TCHAR CmdLineBuffer[1024];
TCHAR DebugCmdLineBuffer[1024];
PWCHAR CmdLine;
USER_PROCESS_DATA UserProcessData;
PROCESS_INFORMATION ProcessInformation;
HANDLE hProcess;
HANDLE hThread;
ULONG ThreadId;
HKEY hKey;
ULONG Result;
ULONG DataSize;
ULONG ExitCode;
MSG Msg;
USEROBJECTFLAGS uof;
//
// See if this is normal SETUP or special Net IDW setup
// during 2nd phase of triple boot; if Net IDW, alter
// WIN.INI the same way the WINLOGON.CMD script would.
//
if ( pGlobals->SetupType == SETUPTYPE_NETIDW ) {
//
// Establish the proper shell for the first real user boot
//
// Until the new shell is fully integrated, read which shell is
// desired from the "DefaultShell" value, and copy it over.
GetProfileString( APPNAME_WINLOGON,
TEXT("DefaultShell"),
TEXT("progman.exe"),
CmdLineBuffer,
sizeof(CmdLineBuffer)/sizeof(WCHAR) );
WriteProfileString( APPNAME_WINLOGON,
TEXT("DefaultShell"),
NULL );
WriteProfileString( APPNAME_WINLOGON,
VARNAME_SHELL,
CmdLineBuffer );
}
//
// Get the Setup command line from the registry
//
if((Result = RegOpenKey( HKEY_LOCAL_MACHINE,
REGNAME_SETUP,
&hKey)) == NO_ERROR) {
DataSize = sizeof(CmdLineBuffer);
Result = RegQueryValueEx( hKey,
VARNAME_SETUPCMD,
NULL,
NULL,
(LPBYTE)CmdLineBuffer,
&DataSize
);
if(Result == NO_ERROR) {
// DebugLog((DEB_ERROR, "Setup cmd line is '%s'",CmdLineBuffer));
} else {
DebugLog((DEB_ERROR, "error %u querying CmdLine value from \\system\\setup",Result));
}
RegCloseKey(hKey);
} else {
DebugLog((DEB_ERROR, "error %u opening \\system\\setup key for CmdLine (2)",Result));
}
// Alter "SetupType" to indicate setup is no long in progress.
SetSetupType( SETUPTYPE_NONE ) ;
#ifdef INIT_REGISTRY
//
// Dont do this if we want to boot an extra time as Administrator
// so we can run winlogon.cmd command script.
if ( pGlobals->SetupType == SETUPTYPE_NETSRW ) {
WriteProfileString( APPNAME_WINLOGON, VARNAME_AUTOLOGON, TEXT("1") );
} else {
#endif
// Delete "AutoAdminLogon" from WIN.INI if present
// except in the retail upgrade case.
if(pGlobals->SetupType != SETUPTYPE_UPGRADE) {
WriteProfileString( APPNAME_WINLOGON, VARNAME_AUTOLOGON, NULL );
}
#ifdef INIT_REGISTRY
}
#endif
RtlZeroMemory(&UserProcessData,sizeof(UserProcessData));
//
// Make windowstation and desktop handles inheritable.
//
GetUserObjectInformation(pGlobals->WindowStation.hwinsta, UOI_FLAGS, &uof, sizeof(uof), NULL);
uof.fInherit = TRUE;
SetUserObjectInformation(pGlobals->WindowStation.hwinsta, UOI_FLAGS, &uof, sizeof(uof));
GetUserObjectInformation(pGlobals->WindowStation.hdeskApplication, UOI_FLAGS, &uof, sizeof(uof), NULL);
uof.fInherit = TRUE;
SetUserObjectInformation(pGlobals->WindowStation.hdeskApplication, UOI_FLAGS, &uof, sizeof(uof));
SetActiveDesktop(&pGlobals->WindowStation, Desktop_Application);
CmdLine = CmdLineBuffer;
#if DEVL
if ( bDebugSetup ) {
wsprintf( DebugCmdLineBuffer, TEXT("ntsd -d %s%s"),
bDebugSetup == 2 ? TEXT("-g -G ") : TEXT(""),
CmdLine
);
CmdLine = DebugCmdLineBuffer;
}
#endif
if(StartSystemProcess( CmdLine,
TEXT("winsta0\\Default"),
0,
0, // Normal startup feedback
NULL,
FALSE,
&hProcess,
NULL) )
{
if (hProcess)
{
//
// Create a second thread to wait on the setup process.
// When setup terminates, the second thread will send us
// a special message. When we receive the special message,
// exit the dispatch loop.
//
// Do this to allow us to respond to messages sent by the
// system, thus preventing the system from hanging.
//
MainThreadId = GetCurrentThreadId();
hThread = CreateThread( NULL,
0,
WaiterThread,
(LPVOID)hProcess,
0,
&ThreadId
);
if(hThread) {
while(GetMessage(&Msg,NULL,0,0)) {
DispatchMessage(&Msg);
}
CloseHandle(hThread);
GetExitCodeProcess(hProcess,&ExitCode);
// BUGBUG look at exit code; may have to restart machine.
} else {
DebugLog((DEB_ERROR, "couldn't start waiter thread"));
}
CloseHandle(hProcess);
} else {
DebugLog((DEB_ERROR, "couldn't get handle to setup process, error = %u",GetLastError()));
}
} else {
DebugLog((DEB_ERROR, "couldn't exec '%ws'",CmdLine));
}
SetActiveDesktop(&pGlobals->WindowStation, Desktop_Winlogon);
}
DWORD
WaiterThread(
PVOID hProcess
)
{
WaitForSingleObject(hProcess,(DWORD)(-1));
PostThreadMessage(MainThreadId,WM_QUIT,0,0);
ExitThread(0);
return(0); // prevent compiler warning
}
VOID
CheckForIncompleteSetup (
PGLOBALS pGlobals
)
/*++
Routine Description:
Checks to see if setup started but never completed.
Do this by checking to see if the SetupInProgress value has been
reset to 0. This value is set to 1 in the default hives that run setup.
Setup.exe resets it to 0 on successful completion.
Arguments:
None.
Return Value:
None
--*/
{
DWORD SetupInProgress = 0 ;
HANDLE KeyHandle = OpenNtRegKey(KEYNAME_SETUP) ;
if (KeyHandle) {
if ( ! ReadRegistry( KeyHandle,
VARNAME_SETUPINPROGRESS,
REG_DWORD,
(TCHAR*) & SetupInProgress,
& SetupInProgress ) ) {
SetupInProgress = 0;
}
NtClose(KeyHandle);
}
//
// If setup did not complete then make them reboot
//
if (SetupInProgress) {
TimeoutMessageBox(pGlobals,
NULL,
IDS_SETUP_INCOMPLETE,
IDS_WINDOWS_MESSAGE,
MB_ICONSTOP | MB_OK
);
#if DBG
//
// On debug builds let them continue if they hold down Ctrl
//
if ((GetKeyState(VK_LCONTROL) < 0) ||
(GetKeyState(VK_RCONTROL) < 0)) {
return;
}
#endif
//
// Reboot time
//
RebootMachine(pGlobals);
}
}
//
// This function checks if the "Repair" value is set. If so, then
// it loads syssetup.dll and calls RepairStartMenuItems
//
VOID
CheckForRepairRequest (void)
{
HKEY hkeyWinlogon;
LONG lResult;
DWORD dwSize, dwType;
BOOL bRunRepair = FALSE;
HINSTANCE hSysSetup;
REPAIRSTARTMENUITEMS RepairStartMenuItems;
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, WINLOGON_KEY,
0, KEY_READ | KEY_WRITE, &hkeyWinlogon) == ERROR_SUCCESS) {
dwSize = sizeof(bRunRepair);
if (RegQueryValueEx (hkeyWinlogon, L"Repair",
NULL, &dwType, (LPBYTE) &bRunRepair,
&dwSize) == ERROR_SUCCESS) {
RegDeleteValue (hkeyWinlogon, L"Repair");
}
RegCloseKey (hkeyWinlogon);
}
if (bRunRepair) {
hSysSetup = LoadLibrary (L"syssetup.dll");
if (hSysSetup) {
RepairStartMenuItems = (REPAIRSTARTMENUITEMS)GetProcAddress(hSysSetup,
"RepairStartMenuItems");
if (RepairStartMenuItems) {
RepairStartMenuItems();
}
FreeLibrary (hSysSetup);
}
}
}