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.
969 lines
29 KiB
969 lines
29 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: sysinit.c
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation
|
|
*
|
|
* Winlogon main module
|
|
*
|
|
* History:
|
|
* 12-09-91 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
BOOLEAN PageFilePopup = FALSE;
|
|
|
|
TCHAR szMemMan[] =
|
|
TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
|
|
|
|
TCHAR szNoPageFile[] = TEXT("TempPageFile");
|
|
|
|
HANDLE hSystemProcesses[MAXIMUM_WAIT_OBJECTS];
|
|
DWORD cSystemProcesses;
|
|
|
|
#define DEBUG_COMMAND TEXT("ntsd -d ")
|
|
#define DEBUG_COMMAND_NO_WAIT TEXT("ntsd -d -g ")
|
|
#define SELECT_DEBUG_COMMAND(x) (x & DEB_DEBUG_NOWAIT ? DEBUG_COMMAND_NO_WAIT : DEBUG_COMMAND)
|
|
|
|
|
|
//
|
|
// Bogus #2: InitializeWinreg is defined in regrpc.h, but we can't include
|
|
// it in any file that uses RegXxx APIs. So, rather than add yet another
|
|
// source file, this is explicitly prototyped here, and any change there has
|
|
// to be reflected here.
|
|
//
|
|
|
|
BOOL
|
|
InitializeWinreg(void);
|
|
|
|
|
|
//
|
|
// Look for autocheck logs, and log them
|
|
//
|
|
|
|
VOID
|
|
DealWithAutochkLogs(
|
|
VOID
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
HANDLE Handle;
|
|
HANDLE DirectoryHandle;
|
|
|
|
POBJECT_DIRECTORY_INFORMATION DirInfo;
|
|
CHAR DirInfoBuffer[ 256 ];
|
|
ULONG Context, Length;
|
|
BOOLEAN RestartScan;
|
|
GLOBALS LocalGlobals;
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
UNICODE_STRING LinkTarget;
|
|
UNICODE_STRING LinkTypeName;
|
|
UNICODE_STRING LinkTargetPrefix;
|
|
WCHAR LinkTargetBuffer[ MAXIMUM_FILENAME_LENGTH ];
|
|
WCHAR LogFile[MAX_PATH];
|
|
HANDLE LogFileHandle;
|
|
DWORD FileSize,BytesRead;
|
|
WCHAR *FileBuffer;
|
|
DWORD ServerRetryCount;
|
|
DWORD rv;
|
|
DWORD gle;
|
|
UINT OldMode;
|
|
|
|
|
|
ZeroMemory(&LocalGlobals,sizeof(LocalGlobals));
|
|
LinkTarget.Buffer = LinkTargetBuffer;
|
|
|
|
DirInfo = (POBJECT_DIRECTORY_INFORMATION)&DirInfoBuffer;
|
|
RestartScan = TRUE;
|
|
RtlInitUnicodeString( &LinkTypeName, L"SymbolicLink" );
|
|
RtlInitUnicodeString( &LinkTargetPrefix, L"\\Device\\Harddisk" );
|
|
|
|
RtlInitUnicodeString( &UnicodeString, L"\\DosDevices" );
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Status = NtOpenDirectoryObject( &DirectoryHandle,
|
|
DIRECTORY_QUERY,
|
|
&ObjectAttributes
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
return;
|
|
}
|
|
|
|
while (TRUE) {
|
|
Status = NtQueryDirectoryObject( DirectoryHandle,
|
|
(PVOID)DirInfo,
|
|
sizeof( DirInfoBuffer ),
|
|
TRUE,
|
|
RestartScan,
|
|
&Context,
|
|
&Length
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (RtlEqualUnicodeString( &DirInfo->TypeName, &LinkTypeName, TRUE ) &&
|
|
DirInfo->Name.Buffer[(DirInfo->Name.Length>>1)-1] == L':') {
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&DirInfo->Name,
|
|
OBJ_CASE_INSENSITIVE,
|
|
DirectoryHandle,
|
|
NULL
|
|
);
|
|
Status = NtOpenSymbolicLinkObject( &Handle,
|
|
SYMBOLIC_LINK_QUERY,
|
|
&ObjectAttributes
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
LinkTarget.Length = 0;
|
|
LinkTarget.MaximumLength = sizeof( LinkTargetBuffer );
|
|
Status = NtQuerySymbolicLinkObject( Handle,
|
|
&LinkTarget,
|
|
NULL
|
|
);
|
|
NtClose( Handle );
|
|
if (NT_SUCCESS( Status ) &&
|
|
RtlPrefixUnicodeString( &LinkTargetPrefix, &LinkTarget, TRUE )
|
|
) {
|
|
|
|
CopyMemory(LogFile,DirInfo->Name.Buffer,DirInfo->Name.Length);
|
|
LogFile[DirInfo->Name.Length >> 1] = (WCHAR)0;
|
|
wcscat(LogFile,L"\\bootex.log");
|
|
|
|
OldMode = SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
|
|
|
|
LogFileHandle = CreateFileW(
|
|
LogFile,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
(VOID )SetErrorMode( OldMode );
|
|
|
|
if ( LogFileHandle != INVALID_HANDLE_VALUE ) {
|
|
FileSize = GetFileSize(LogFileHandle,NULL);
|
|
if ( FileSize != 0xffffffff ) {
|
|
|
|
//
|
|
// truncate the file data if necessary
|
|
//
|
|
if ( FileSize > 32000 ) {
|
|
FileSize = 32000;
|
|
}
|
|
FileBuffer = LocalAlloc(LMEM_FIXED,FileSize+sizeof(WCHAR));
|
|
if ( FileBuffer ) {
|
|
FileBuffer[FileSize>>1] = (WCHAR)'\0';
|
|
if ( ReadFile(LogFileHandle,FileBuffer,FileSize,&BytesRead,NULL) ) {
|
|
FileBuffer[BytesRead>>1] = (WCHAR)'\0';
|
|
|
|
ServerRetryCount = 0;
|
|
tryagain:
|
|
LocalGlobals.hEventLog = RegisterEventSource(
|
|
NULL,
|
|
TEXT("Autochk")
|
|
);
|
|
if ( LocalGlobals.hEventLog ) {
|
|
rv = ReportWinlogonEvent(
|
|
&LocalGlobals,
|
|
EVENTLOG_INFORMATION_TYPE,
|
|
EVENT_AUTOCHK_DATA,
|
|
0,
|
|
NULL,
|
|
1,
|
|
FileBuffer
|
|
);
|
|
DeregisterEventSource(LocalGlobals.hEventLog);
|
|
LocalGlobals.hEventLog = NULL;
|
|
NtClose(LogFileHandle);
|
|
LogFileHandle = INVALID_HANDLE_VALUE;
|
|
if ( rv == ERROR_SUCCESS ) {
|
|
DeleteFile(LogFile);
|
|
}
|
|
}
|
|
else {
|
|
gle = GetLastError();
|
|
if ( (gle == RPC_S_SERVER_UNAVAILABLE ||
|
|
gle == RPC_S_UNKNOWN_IF)
|
|
&& ServerRetryCount < 10 ) {
|
|
Sleep(1000);
|
|
ServerRetryCount++;
|
|
goto tryagain;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
if (LogFileHandle != INVALID_HANDLE_VALUE ) {
|
|
NtClose(LogFileHandle);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
RestartScan = FALSE;
|
|
if (!NT_SUCCESS( Status )) {
|
|
break;
|
|
}
|
|
}
|
|
NtClose(DirectoryHandle);
|
|
return;
|
|
}
|
|
|
|
|
|
DWORD FontLoaderThread( void )
|
|
{
|
|
LoadLocalFonts();
|
|
ExitThread(0);
|
|
return(0); // prevent compiler warning
|
|
}
|
|
|
|
HANDLE
|
|
StartLoadingFonts(void)
|
|
{
|
|
HANDLE hThread;
|
|
DWORD ThreadId = 0;
|
|
|
|
hThread = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) FontLoaderThread,
|
|
0,
|
|
0,
|
|
&ThreadId
|
|
);
|
|
|
|
//
|
|
// We don't need this handle (we're not going to wait), so get rid of
|
|
// it now, rather than later.
|
|
//
|
|
|
|
return( hThread );
|
|
}
|
|
|
|
|
|
BOOL InitSystemFontInfo(
|
|
PGLOBALS pGlobals
|
|
)
|
|
{
|
|
TCHAR *FontNames, *FontName;
|
|
TCHAR FontPath[ MAX_PATH ];
|
|
ULONG cb = 63 * 1024;
|
|
|
|
|
|
FontNames = Alloc( cb );
|
|
ASSERTMSG("Winlogon failed to allocate memory for reading font information", FontNames != NULL);
|
|
if (FontNames == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetProfileString( TEXT("Fonts"), NULL, TEXT(""), FontNames, cb )) {
|
|
FontName = FontNames;
|
|
while (*FontName) {
|
|
if (GetProfileString( TEXT("Fonts"), FontName, TEXT(""), FontPath, sizeof( FontPath ) )) {
|
|
switch (AddFontResource( FontPath )) {
|
|
case 0:
|
|
KdPrint(("WINLOGON: Unable to add new font path: %ws\n", FontPath ));
|
|
break;
|
|
|
|
case 1:
|
|
KdPrint(("WINLOGON: Found new font path: %ws\n", FontPath ));
|
|
break;
|
|
|
|
default:
|
|
KdPrint(("WINLOGON: Found existing font path: %ws\n", FontPath ));
|
|
RemoveFontResource( FontPath );
|
|
break;
|
|
}
|
|
}
|
|
while (*FontName++) ;
|
|
}
|
|
} else {
|
|
KdPrint(("WINLOGON: Unable to read font info from win.ini - %u\n", GetLastError()));
|
|
}
|
|
|
|
Free( FontNames );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* SetProcessPriority
|
|
*
|
|
* Sets the priority of the winlogon process.
|
|
*
|
|
* History:
|
|
* 18-May-1992 Davidc Created.
|
|
\***************************************************************************/
|
|
BOOL SetProcessPriority(
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Bump us up to the high priority class
|
|
//
|
|
|
|
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
|
|
DebugLog((DEB_ERROR, "Failed to raise it's own process priority, error = %d", GetLastError()));
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Set this thread to high priority since we'll be handling all input
|
|
//
|
|
|
|
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
|
|
DebugLog((DEB_ERROR, "Failed to raise main thread priority, error = %d", GetLastError()));
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
VOID
|
|
CreateTemporaryPageFile()
|
|
{
|
|
LONG FileSizeInMegabytes;
|
|
UNICODE_STRING PagingFileName;
|
|
NTSTATUS st;
|
|
LARGE_INTEGER MinPagingFileSize;
|
|
LARGE_INTEGER MaxPagingFileSize;
|
|
UNICODE_STRING FileName;
|
|
BOOLEAN TranslationStatus;
|
|
TCHAR TemporaryPageFile[MAX_PATH+1];
|
|
NTSTATUS PfiStatus,PiStatus;
|
|
ULONG ReturnLength;
|
|
SYSTEM_PAGEFILE_INFORMATION pfi;
|
|
SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
|
|
HKEY hkeyMM;
|
|
DWORD dwRegData = 0;
|
|
|
|
|
|
GetSystemDirectory(TemporaryPageFile,sizeof(TemporaryPageFile));
|
|
wcscat(TemporaryPageFile,TEXT("\\temppf.sys"));
|
|
DeleteFile(TemporaryPageFile);
|
|
|
|
//
|
|
// Check to see if we have a pagefile, warn the user if we don't
|
|
//
|
|
|
|
PfiStatus = NtQuerySystemInformation(
|
|
SystemPageFileInformation,
|
|
&pfi,
|
|
sizeof(pfi),
|
|
&ReturnLength
|
|
);
|
|
|
|
PiStatus = NtQuerySystemInformation(
|
|
SystemPerformanceInformation,
|
|
&PerfInfo,
|
|
sizeof(PerfInfo),
|
|
NULL
|
|
);
|
|
//
|
|
// if you have no page file, or your total commit limit is at it's minimum,
|
|
// then create an additional pagefile and tel the user to do something...
|
|
//
|
|
|
|
if ( (NT_SUCCESS(PfiStatus) && (ReturnLength == 0)) ||
|
|
(NT_SUCCESS(PiStatus) && PerfInfo.CommitLimit <= 5500 ) ) {
|
|
|
|
//
|
|
// Set a flag in registry so USERINIT knows to run VMApp.
|
|
//
|
|
dwRegData = 1;
|
|
|
|
PageFilePopup = TRUE;
|
|
|
|
//
|
|
// create a temporary pagefile to get us through logon/control
|
|
// panel activation
|
|
//
|
|
//
|
|
|
|
GetSystemDirectory(TemporaryPageFile,sizeof(TemporaryPageFile));
|
|
lstrcat(TemporaryPageFile,TEXT("\\temppf.sys"));
|
|
|
|
|
|
//
|
|
// Start with a 20mb pagefile
|
|
//
|
|
|
|
FileSizeInMegabytes = 20;
|
|
|
|
RtlInitUnicodeString(&PagingFileName, TemporaryPageFile);
|
|
|
|
MinPagingFileSize = RtlEnlargedIntegerMultiply(FileSizeInMegabytes,0x100000);
|
|
MaxPagingFileSize = MinPagingFileSize;
|
|
|
|
|
|
TranslationStatus = RtlDosPathNameToNtPathName_U(
|
|
PagingFileName.Buffer,
|
|
&FileName,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if ( TranslationStatus ) {
|
|
|
|
retry:
|
|
st = NtCreatePagingFile(
|
|
(PUNICODE_STRING)&FileName,
|
|
&MinPagingFileSize,
|
|
&MaxPagingFileSize,
|
|
0
|
|
);
|
|
|
|
if (!NT_SUCCESS( st )) {
|
|
|
|
if ( FileSizeInMegabytes > 0 ) {
|
|
FileSizeInMegabytes -= 2;
|
|
MinPagingFileSize = RtlEnlargedIntegerMultiply(FileSizeInMegabytes,0x100000);
|
|
MaxPagingFileSize = MinPagingFileSize;
|
|
goto retry;
|
|
}
|
|
} else {
|
|
MoveFileExW(PagingFileName.Buffer,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
|
|
|
|
}
|
|
|
|
RtlFreeHeap(RtlProcessHeap(), 0, FileName.Buffer);
|
|
|
|
}
|
|
}
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMemMan, 0,
|
|
KEY_WRITE, &hkeyMM) == ERROR_SUCCESS) {
|
|
if (dwRegData == 1) {
|
|
RegSetValueEx (hkeyMM, szNoPageFile, 0, REG_DWORD,
|
|
(LPBYTE)&dwRegData, sizeof(dwRegData));
|
|
} else
|
|
RegDeleteValue(hkeyMM, (LPTSTR)szNoPageFile);
|
|
RegCloseKey(hkeyMM);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
StartSystemProcess(
|
|
PWSTR pszCommandLine,
|
|
PWSTR pszDesktop,
|
|
DWORD Flags,
|
|
DWORD StartupFlags,
|
|
PVOID pEnvironment,
|
|
BOOLEAN fSaveHandle,
|
|
HANDLE *phProcess,
|
|
HANDLE *phThread
|
|
)
|
|
{
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
BOOL Result;
|
|
#if DBG
|
|
WCHAR szExtra[MAX_PATH];
|
|
#endif
|
|
|
|
//
|
|
// Initialize process startup info
|
|
//
|
|
ZeroMemory(&si, sizeof(STARTUPINFO));
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.lpReserved = pszCommandLine;
|
|
si.lpTitle = pszCommandLine;
|
|
si.dwFlags = StartupFlags;
|
|
si.wShowWindow = SW_SHOW; // at least let the guy see it
|
|
si.lpDesktop = pszDesktop;
|
|
|
|
//
|
|
// Special debug helpers for our friends
|
|
//
|
|
#if DBG
|
|
if ((WinlogonInfoLevel & DEB_DEBUG_LSA) &&
|
|
((wcsncmp(pszCommandLine, TEXT("lsass"), 5) == 0) ||
|
|
(wcsncmp(pszCommandLine, TEXT("spmgr"), 5) == 0) ))
|
|
{
|
|
wcscpy(szExtra, SELECT_DEBUG_COMMAND(WinlogonInfoLevel));
|
|
wcscat(szExtra, pszCommandLine);
|
|
pszCommandLine = szExtra;
|
|
}
|
|
if ((WinlogonInfoLevel & DEB_DEBUG_MPR) &&
|
|
(wcsncmp(pszCommandLine, TEXT("mpnotify"), 8) == 0))
|
|
{
|
|
wcscpy(szExtra, SELECT_DEBUG_COMMAND(WinlogonInfoLevel));
|
|
wcscat(szExtra, pszCommandLine);
|
|
pszCommandLine = szExtra;
|
|
}
|
|
if ((WinlogonInfoLevel & DEB_DEBUG_SERVICES) &&
|
|
(wcsncmp(pszCommandLine, TEXT("services"), 8) == 0))
|
|
{
|
|
wcscpy(szExtra, SELECT_DEBUG_COMMAND(WinlogonInfoLevel));
|
|
wcscat(szExtra, pszCommandLine);
|
|
pszCommandLine = szExtra;
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// Create the app suspended
|
|
//
|
|
Result = CreateProcess(NULL,
|
|
pszCommandLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
Flags | CREATE_UNICODE_ENVIRONMENT,
|
|
pEnvironment,
|
|
NULL,
|
|
&si,
|
|
&pi);
|
|
|
|
|
|
if (Result)
|
|
{
|
|
if (!phProcess)
|
|
{
|
|
if (fSaveHandle)
|
|
{
|
|
if (cSystemProcesses < MAXIMUM_WAIT_OBJECTS)
|
|
{
|
|
hSystemProcesses[cSystemProcesses++] = pi.hProcess;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(pi.hProcess);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*phProcess = pi.hProcess;
|
|
}
|
|
if (!phThread)
|
|
{
|
|
CloseHandle(pi.hThread);
|
|
}
|
|
else
|
|
{
|
|
*phThread = pi.hThread;
|
|
}
|
|
}
|
|
|
|
return(Result);
|
|
}
|
|
|
|
|
|
BOOL
|
|
ExecSystemProcesses(
|
|
PGLOBALS pGlobals
|
|
)
|
|
{
|
|
BOOL SystemStarted = FALSE ;
|
|
SYSTEM_CRASH_STATE_INFORMATION CrashState;
|
|
PWSTR pszStartLine;
|
|
PWSTR pszTok;
|
|
DWORD dwStarted = 0;
|
|
PVOID pEnvironment;
|
|
|
|
//
|
|
// Initialize the shutdown server
|
|
//
|
|
|
|
RpcpInitRpcServer();
|
|
if ( !InitializeShutdownModule( pGlobals ) ) {
|
|
ASSERT( FALSE );
|
|
DebugLog((DEB_ERROR, "Cannot InitializeShutdownModule."));
|
|
}
|
|
|
|
//
|
|
// Initialize the registry server
|
|
//
|
|
// NB: This is prototyped local to this file. Any change must be
|
|
// reflected above.
|
|
//
|
|
|
|
if ( !InitializeWinreg() ) {
|
|
ASSERT( FALSE );
|
|
DebugLog((DEB_ERROR, "Cannot InitializeWinreg."));
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// must start services.exe server before anything else. If there is an
|
|
// entry ServiceControllerStart in win.ini, use it as the command.
|
|
//
|
|
pszStartLine = AllocAndGetProfileString(APPLICATION_NAME,
|
|
TEXT("ServiceControllerStart"),
|
|
TEXT("services.exe"));
|
|
|
|
if (!pszStartLine)
|
|
{
|
|
DebugLog((DEB_ERROR, "Can't allocate space, so this exec probably won't work\n"));
|
|
pszStartLine = TEXT("services.exe");
|
|
}
|
|
|
|
if (CreateUserEnvironment(&pEnvironment))
|
|
{
|
|
SetupBasicEnvironment(&pEnvironment);
|
|
}
|
|
else
|
|
{
|
|
DebugLog((DEB_ERROR, "Failed to create initial environment\n"));
|
|
|
|
//
|
|
// Set this to NULL, and let CreateProcess deal with any
|
|
// memory constraints.
|
|
//
|
|
pEnvironment = NULL;
|
|
}
|
|
|
|
if (!StartSystemProcess(pszStartLine,
|
|
APPLICATION_DESKTOP_NAME,
|
|
0,
|
|
STARTF_FORCEOFFFEEDBACK,
|
|
pEnvironment,
|
|
FALSE, // Don't stash this handle away
|
|
NULL, NULL))
|
|
{
|
|
DebugLog((DEB_ERROR, "Couldn't start %ws, %d\n", pszStartLine, GetLastError()));
|
|
}
|
|
|
|
else
|
|
{
|
|
HANDLE hRPCRegServer;
|
|
int error,
|
|
i = 0 ;
|
|
|
|
while(i < 20000) {
|
|
Sleep(1000); i+=1000;
|
|
if (hRPCRegServer = OpenEventA(SYNCHRONIZE, FALSE, "Microsoft.RPC_Registry_Server")) {
|
|
//WLPrint(("RPC_Registry_Server event openned"));
|
|
error = WaitForSingleObject(hRPCRegServer, 100);
|
|
CloseHandle(hRPCRegServer);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Free(pszStartLine);
|
|
|
|
//
|
|
// If this is standard installation or network installation, we need to
|
|
// create an event to stall lsa security initialization. In the case of
|
|
// WINNT -> WINNT and AS -> AS upgrade we shouldn't stall LSA.
|
|
//
|
|
if (pGlobals->fExecuteSetup && (pGlobals->SetupType != SETUPTYPE_UPGRADE)) {
|
|
CreateLsaStallEvent();
|
|
}
|
|
|
|
//
|
|
// If there is a system dump available, start up the save dump process to
|
|
// capture it so that it doesn't use as much paging file so that it is
|
|
// available for system use.
|
|
//
|
|
|
|
NtQuerySystemInformation( SystemCrashDumpStateInformation,
|
|
&CrashState,
|
|
sizeof( CrashState ),
|
|
(PULONG) NULL );
|
|
if (CrashState.ValidCrashDump) {
|
|
pszStartLine = AllocAndGetProfileString(APPLICATION_NAME,
|
|
TEXT("SaveDumpStart"),
|
|
TEXT("savedump.exe"));
|
|
|
|
|
|
if (!StartSystemProcess(pszStartLine,
|
|
APPLICATION_DESKTOP_NAME,
|
|
0,
|
|
STARTF_FORCEOFFFEEDBACK,
|
|
pEnvironment,
|
|
FALSE, // Don't care about syncing later
|
|
NULL, NULL))
|
|
{
|
|
DebugLog((DEB_ERROR, "Couldn't start %ws, %d\n", pszStartLine, GetLastError()));
|
|
}
|
|
Free(pszStartLine);
|
|
}
|
|
|
|
//
|
|
// Startup system processes
|
|
// These must be started for authentication initialization to succeed
|
|
// because one of the system processes is the LSA server.
|
|
//
|
|
pszStartLine = AllocAndGetProfileString(APPLICATION_NAME,
|
|
TEXT("System"),
|
|
NULL);
|
|
|
|
pszTok = wcstok(pszStartLine, TEXT(","));
|
|
while (pszTok)
|
|
{
|
|
//
|
|
// Skip any blanks...
|
|
//
|
|
if (*pszTok == TEXT(' '))
|
|
{
|
|
while (*pszTok++ == TEXT(' '))
|
|
;
|
|
}
|
|
|
|
if (StartSystemProcess( pszTok,
|
|
APPLICATION_DESKTOP_NAME,
|
|
0,
|
|
STARTF_FORCEOFFFEEDBACK,
|
|
pEnvironment,
|
|
TRUE, // Save this handle to sync with
|
|
NULL, NULL))
|
|
{
|
|
dwStarted++;
|
|
}
|
|
pszTok = wcstok(NULL, TEXT(","));
|
|
|
|
}
|
|
|
|
Free(pszStartLine);
|
|
|
|
RtlDestroyEnvironment(pEnvironment);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* InitializeSound
|
|
*
|
|
* Set up a global function variable to address the sound playing routine.
|
|
* If no wave devices are present, this variable will remain 0 and no sound
|
|
* will be made by WinLogon.
|
|
*
|
|
* History:
|
|
* 6-May-1992 SteveDav Created
|
|
\***************************************************************************/
|
|
void InitializeSound(
|
|
PGLOBALS pGlobals)
|
|
{
|
|
//
|
|
// Load the sound playing module. If no wave devices are available
|
|
// free the library, and set the address of the sound function to 0
|
|
//
|
|
|
|
CHAR ResourceString[MAX_STRING_BYTES];
|
|
HANDLE hLib;
|
|
|
|
// Set the initial value (should not be necessary)
|
|
pGlobals->PlaySound = NULL;
|
|
pGlobals->MigrateSoundEvents = NULL;
|
|
|
|
//
|
|
// Get name of sound library
|
|
//
|
|
if (!LoadStringA(NULL, IDS_SOUND_DLL, ResourceString, sizeof(ResourceString))) {
|
|
// Cannot get the name of the sound library
|
|
return;
|
|
}
|
|
|
|
hLib = LoadLibraryA(ResourceString);
|
|
|
|
if (hLib) {
|
|
|
|
/* We must use the Ascii version of LoadString as GetProcAddress */
|
|
/* takes an Ascii string only... */
|
|
|
|
/* Whenever a user logs in, have WINMM.DLL check if there are any */
|
|
/* sound events within the [SOUNDS] section of CONTROL.INI that */
|
|
/* haven't been ported into HKCU/AppEvents. Here, we find the */
|
|
/* relevant routine within WINMM.DLL so it can be called when */
|
|
/* appropriate. */
|
|
|
|
if (!LoadStringA(NULL, IDS_MIGRATESOUNDEVENTS, ResourceString, sizeof(ResourceString))) {
|
|
/* we do not know the name of the routine to call */
|
|
pGlobals->MigrateSoundEvents = NULL;
|
|
} else {
|
|
pGlobals->MigrateSoundEvents = (SOUNDPROC)GetProcAddress(hLib, ResourceString);
|
|
}
|
|
|
|
if (!LoadStringA(NULL, IDS_WAVEOUTGETNUMDEVS, ResourceString, sizeof(ResourceString))) {
|
|
/* we do not know the name of the routine to call */
|
|
//return; We must free the library...
|
|
} else {
|
|
pGlobals->PlaySound = (SOUNDPROC)GetProcAddress(hLib, ResourceString);
|
|
}
|
|
|
|
if (pGlobals->PlaySound) {
|
|
/* See how many wave devices there are - if none, or we fail
|
|
* to load the name of PlaySound, then unload WINMM and never
|
|
* try and call it again.
|
|
*/
|
|
UINT n;
|
|
n = (UINT)(*(pGlobals->PlaySound))();
|
|
if (n &&
|
|
LoadStringA(NULL, IDS_PLAYSOUND, ResourceString, sizeof(ResourceString))) {
|
|
pGlobals->PlaySound = (SOUNDPROC)GetProcAddress(hLib, ResourceString);
|
|
} else {
|
|
pGlobals->PlaySound = NULL;
|
|
//DebugLog((DEB_ERROR, "Winlogon: NO WAVE devices"));
|
|
}
|
|
}
|
|
|
|
if (!pGlobals->PlaySound && !pGlobals->MigrateSoundEvents) {
|
|
//DebugLog((DEB_ERROR, "Winlogon: Unloading WINMM"));
|
|
FreeLibrary(hLib);
|
|
}
|
|
|
|
}
|
|
#if DBG
|
|
else { /* Could not load WINMM */
|
|
DebugLog((DEB_ERROR, "Could not load WINMM")); // Keep this debug message. It's an error
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* InitializeMidi
|
|
*
|
|
* Set up a global function variable to address the Midi Migrate User routine.
|
|
*
|
|
* History:
|
|
* 1-3-96 ShawnB Created
|
|
\***************************************************************************/
|
|
void InitializeMidi(
|
|
PGLOBALS pGlobals)
|
|
{
|
|
//
|
|
// Load the Midi Migration module.
|
|
//
|
|
|
|
CHAR ResourceString[MAX_STRING_BYTES];
|
|
HMODULE hModule;
|
|
BOOL fFreeLib;
|
|
|
|
// Set the initial value (should not be necessary)
|
|
pGlobals->MigrateMidiUser = NULL;
|
|
|
|
//
|
|
// Get name of Midi library
|
|
//
|
|
if (!LoadStringA(NULL, IDS_MIDI_DLL, ResourceString, sizeof(ResourceString))) {
|
|
// Cannot get the name of the Midi library
|
|
return;
|
|
}
|
|
|
|
// Check if Already loaded (by InitializeSound)
|
|
hModule = GetModuleHandleA(ResourceString);
|
|
if (!hModule)
|
|
{
|
|
// Load it ourselves
|
|
hModule = (HMODULE)LoadLibraryA(ResourceString);
|
|
fFreeLib = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fFreeLib = FALSE;
|
|
}
|
|
|
|
if (hModule) {
|
|
|
|
/* We must use the Ascii version of LoadString as GetProcAddress */
|
|
/* takes an Ascii string only... */
|
|
|
|
/* Whenever a user logs in, have WINMM.DLL check if the user needs */
|
|
/* their MIDI registry info updated. Here, we find the */
|
|
/* relevant routine within WINMM.DLL so it can be called when */
|
|
/* appropriate. */
|
|
|
|
if (!LoadStringA(NULL, IDS_MIGRATEMIDIUSER, ResourceString, sizeof(ResourceString))) {
|
|
/* we do not know the name of the routine to call */
|
|
pGlobals->MigrateMidiUser = NULL;
|
|
} else {
|
|
pGlobals->MigrateMidiUser = (MIDIPROC)GetProcAddress(hModule, ResourceString);
|
|
}
|
|
|
|
|
|
if (!pGlobals->MigrateMidiUser) {
|
|
//DebugLog((DEB_ERROR, "Winlogon: Unloading WINMM"));
|
|
if (fFreeLib)
|
|
{
|
|
FreeLibrary(hModule);
|
|
}
|
|
}
|
|
|
|
}
|
|
#if DBG
|
|
else { /* Could not load WINMM */
|
|
DebugLog((DEB_ERROR, "Could not load WINMM")); // Keep this debug message. It's an error
|
|
}
|
|
#endif
|
|
} // End InitializeMidi
|
|
|
|
BOOL
|
|
WaitForSystemProcesses(
|
|
PGLOBALS pGlobals)
|
|
{
|
|
DWORD i;
|
|
DWORD Exit;
|
|
|
|
//
|
|
// First, verify all handles:
|
|
//
|
|
|
|
for (i = 0; i < cSystemProcesses ; i++ )
|
|
{
|
|
|
|
WaitLoopTop:
|
|
|
|
if (GetExitCodeProcess(hSystemProcesses[i], &Exit))
|
|
{
|
|
if (Exit == STILL_ACTIVE)
|
|
{
|
|
//
|
|
// Ooh, a good one. Keep it.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Bad handle, one way or another
|
|
//
|
|
|
|
CloseHandle(hSystemProcesses[i]);
|
|
hSystemProcesses[i] = hSystemProcesses[--cSystemProcesses];
|
|
|
|
if (i != cSystemProcesses)
|
|
{
|
|
goto WaitLoopTop; // Retry same index, but do not increment
|
|
}
|
|
|
|
}
|
|
|
|
if (!cSystemProcesses)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
Exit = WaitForMultipleObjectsEx( cSystemProcesses,
|
|
hSystemProcesses,
|
|
FALSE,
|
|
4000,
|
|
FALSE );
|
|
|
|
|
|
return(Exit != WAIT_TIMEOUT);
|
|
}
|