reactos/reactos/subsystems/win32/csrss/init.c

686 lines
18 KiB
C
Raw Normal View History

/* $Id$
*
* reactos/subsys/csrss/init.c
*
* Initialize the CSRSS subsystem server process.
*
* ReactOS Operating System
*
*/
/* INCLUDES ******************************************************************/
#include <csrss.h>
#define NDEBUG
2003-08-11 Casper S. Hornstrup <chorns@users.sourceforge.net> * bootdata/txtsetup.sif (SetupData): Add /NOBOOTSCREEN to OsLoadOptions. * hal/halx86/display.c (CHAR_ATTRIBUTE_BLACK): Define. (HalClearDisplay): Add CharAttribute parameter. (HalInitializeDisplay, HalReleaseDisplayOwnership): Blue screen. * hal/halx86/halinit.c (DriverEntry): Blue screen for boot phase 2. * include/reactos/resource.h (IDB_BOOTIMAGE): Define. * ntoskrnl/Makefile: Add boot video objects. * ntoskrnl/Makefile.i386: Ditto. * ntoskrnl/ntoskrnl.def: Add boot video exports. * ntoskrnl/ntoskrnl.edf: Ditto. * ntoskrnl/ntoskrnl.rc (IDB_BOOTIMAGE): Define. * ntoskrnl/include/internal/kd.h (KdInit3): Add. * ntoskrnl/kd/kdebug.c (KdInitSystem): Print information in KdInit3. * ntoskrnl/ke/bug.c (KeBugCheckWithTf, KeBugCheckEx): Switch to text-mode on crash if needed. * ntoskrnl/ke/main.c (ExpInitializeExecutive): Display bootscreen image during boot. * ntoskrnl/ke/i386/v86m_sup.S (_KiV86Complete): Restore previous mode and old exception handler list. * subsys/csrss/init.c: Change PrintString to DPRINT1. * subsys/smss/init.c: Change PrintString to DPRINT1. (SignalInitEvent): New. (InitSessionManager): Call SignalInitEvent to switch to text-mode if needed. * subsys/smss/smss.c: Change PrintString to DPRINT1. * ntoskrnl/inbv: New directory. * ntoskrnl/inbv/i386: Ditto. * ntoskrnl/res: Ditto. * include/ntos/bootvid.h: New file. * ntoskrnl/inbv/.cvsignore: Ditto. * ntoskrnl/inbv/bootvid.c: Ditto. * ntoskrnl/inbv/inbv.c: Ditto. * ntoskrnl/inbv/i386/.cvsignore: Ditto. * ntoskrnl/inbv/i386/pixelsup.S: Ditto. * ntoskrnl/res/bootimage.bmp: Ditto. svn path=/trunk/; revision=5529
2003-08-11 18:50:12 +00:00
#include <debug.h>
/* GLOBALS ******************************************************************/
HANDLE CsrHeap = (HANDLE) 0;
HANDLE CsrObjectDirectory = (HANDLE) 0;
UNICODE_STRING CsrDirectoryName;
extern HANDLE CsrssApiHeap;
static unsigned InitCompleteProcCount;
static CSRPLUGIN_INIT_COMPLETE_PROC *InitCompleteProcs = NULL;
static unsigned HardErrorProcCount;
static CSRPLUGIN_HARDERROR_PROC *HardErrorProcs = NULL;
HANDLE hSbApiPort = (HANDLE) 0;
HANDLE hBootstrapOk = (HANDLE) 0;
HANDLE hSmApiPort = (HANDLE) 0;
HANDLE hApiPort = (HANDLE) 0;
/**********************************************************************
* CsrpAddInitCompleteProc/1
*/
static NTSTATUS FASTCALL
CsrpAddInitCompleteProc(CSRPLUGIN_INIT_COMPLETE_PROC Proc)
{
CSRPLUGIN_INIT_COMPLETE_PROC *NewProcs;
DPRINT("CSR: %s called\n", __FUNCTION__);
NewProcs = RtlAllocateHeap(CsrssApiHeap, 0,
(InitCompleteProcCount + 1)
* sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
if (NULL == NewProcs)
{
return STATUS_NO_MEMORY;
}
if (0 != InitCompleteProcCount)
{
RtlCopyMemory(NewProcs, InitCompleteProcs,
InitCompleteProcCount * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
}
NewProcs[InitCompleteProcCount] = Proc;
InitCompleteProcs = NewProcs;
InitCompleteProcCount++;
return STATUS_SUCCESS;
}
static NTSTATUS FASTCALL
CsrpAddHardErrorProc(CSRPLUGIN_HARDERROR_PROC Proc)
{
CSRPLUGIN_HARDERROR_PROC *NewProcs;
DPRINT("CSR: %s called\n", __FUNCTION__);
NewProcs = RtlAllocateHeap(CsrssApiHeap, 0,
(HardErrorProcCount + 1)
* sizeof(CSRPLUGIN_HARDERROR_PROC));
if (NULL == NewProcs)
{
return STATUS_NO_MEMORY;
}
if (0 != HardErrorProcCount)
{
RtlCopyMemory(NewProcs, HardErrorProcs,
HardErrorProcCount * sizeof(CSRPLUGIN_HARDERROR_PROC));
RtlFreeHeap(CsrssApiHeap, 0, HardErrorProcs);
}
NewProcs[HardErrorProcCount] = Proc;
HardErrorProcs = NewProcs;
HardErrorProcCount++;
return STATUS_SUCCESS;
}
/**********************************************************************
* CallInitComplete/0
*/
static BOOL FASTCALL
CallInitComplete(void)
{
BOOL Ok;
unsigned i;
DPRINT("CSR: %s called\n", __FUNCTION__);
Ok = TRUE;
if (0 != InitCompleteProcCount)
{
for (i = 0; i < InitCompleteProcCount && Ok; i++)
{
Ok = (*(InitCompleteProcs[i]))();
}
RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
}
return Ok;
}
BOOL
FASTCALL
CallHardError(void)
{
BOOL Ok;
unsigned i;
DPRINT("CSR: %s called\n", __FUNCTION__);
Ok = TRUE;
if (0 != HardErrorProcCount)
{
for (i = 0; i < HardErrorProcCount && Ok; i++)
{
Ok = (*(HardErrorProcs[i]))();
}
}
return Ok;
}
ULONG
InitializeVideoAddressSpace(VOID);
/**********************************************************************
* CsrpCreateObjectDirectory/3
*/
static NTSTATUS
CsrpCreateObjectDirectory (int argc, char ** argv, char ** envp)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES Attributes;
DPRINT("CSR: %s called\n", __FUNCTION__);
/* create object directory ('\Windows') */
RtlCreateUnicodeString (&CsrDirectoryName,
L"\\Windows");
InitializeObjectAttributes (&Attributes,
&CsrDirectoryName,
OBJ_OPENIF,
NULL,
NULL);
Status = NtOpenDirectoryObject(&CsrObjectDirectory,
DIRECTORY_ALL_ACCESS,
&Attributes);
return Status;
}
/**********************************************************************
* CsrpInitVideo/3
*
* TODO: we need a virtual device for sessions other than
* TODO: the console one
*/
static NTSTATUS
CsrpInitVideo (int argc, char ** argv, char ** envp)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\??\\DISPLAY1");
IO_STATUS_BLOCK Iosb;
HANDLE VideoHandle = (HANDLE) 0;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("CSR: %s called\n", __FUNCTION__);
InitializeVideoAddressSpace();
InitializeObjectAttributes(&ObjectAttributes,
&DeviceName,
0,
NULL,
NULL);
Status = NtOpenFile(&VideoHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&Iosb,
0,
0);
if (NT_SUCCESS(Status))
{
NtClose(VideoHandle);
}
return Status;
}
/**********************************************************************
* CsrpInitWin32Csr/3
*
* TODO: this function should be turned more general to load an
* TODO: hosted server DLL as received from the command line;
* TODO: for instance: ServerDll=winsrv:ConServerDllInitialization,2
* TODO: ^method ^dll ^api ^sid
* TODO:
* TODO: CsrpHostServerDll (LPWSTR DllName,
* TODO: LPWSTR ApiName,
* TODO: DWORD ServerId)
*/
static NTSTATUS
CsrpInitWin32Csr (int argc, char ** argv, char ** envp)
{
NTSTATUS Status;
UNICODE_STRING DllName;
HINSTANCE hInst;
ANSI_STRING ProcName;
CSRPLUGIN_INITIALIZE_PROC InitProc;
CSRSS_EXPORTED_FUNCS Exports;
PCSRSS_API_DEFINITION ApiDefinitions;
PCSRSS_OBJECT_DEFINITION ObjectDefinitions;
CSRPLUGIN_INIT_COMPLETE_PROC InitCompleteProc;
CSRPLUGIN_HARDERROR_PROC HardErrorProc;
DPRINT("CSR: %s called\n", __FUNCTION__);
RtlInitUnicodeString(&DllName, L"win32csr.dll");
Status = LdrLoadDll(NULL, 0, &DllName, (PVOID *) &hInst);
if (! NT_SUCCESS(Status))
{
return Status;
}
RtlInitAnsiString(&ProcName, "Win32CsrInitialization");
Status = LdrGetProcedureAddress(hInst, &ProcName, 0, (PVOID *) &InitProc);
if (! NT_SUCCESS(Status))
{
return Status;
}
Exports.CsrInsertObjectProc = CsrInsertObject;
Exports.CsrGetObjectProc = CsrGetObject;
Exports.CsrReleaseObjectProc = CsrReleaseObject;
Exports.CsrEnumProcessesProc = CsrEnumProcesses;
if (! (*InitProc)(&ApiDefinitions, &ObjectDefinitions, &InitCompleteProc,
&HardErrorProc, &Exports, CsrssApiHeap))
{
return STATUS_UNSUCCESSFUL;
}
Status = CsrApiRegisterDefinitions(ApiDefinitions);
if (! NT_SUCCESS(Status))
{
return Status;
}
Status = CsrRegisterObjectDefinitions(ObjectDefinitions);
if (! NT_SUCCESS(Status))
{
return Status;
}
if (NULL != InitCompleteProc)
{
Status = CsrpAddInitCompleteProc(InitCompleteProc);
}
if (HardErrorProc) Status = CsrpAddHardErrorProc(HardErrorProc);
return Status;
}
CSRSS_API_DEFINITION NativeDefinitions[] =
{
CSRSS_DEFINE_API(CREATE_PROCESS, CsrCreateProcess),
CSRSS_DEFINE_API(TERMINATE_PROCESS, CsrTerminateProcess),
CSRSS_DEFINE_API(CONNECT_PROCESS, CsrConnectProcess),
CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS, CsrRegisterServicesProcess),
CSRSS_DEFINE_API(GET_SHUTDOWN_PARAMETERS, CsrGetShutdownParameters),
CSRSS_DEFINE_API(SET_SHUTDOWN_PARAMETERS, CsrSetShutdownParameters),
CSRSS_DEFINE_API(GET_INPUT_HANDLE, CsrGetInputHandle),
CSRSS_DEFINE_API(GET_OUTPUT_HANDLE, CsrGetOutputHandle),
CSRSS_DEFINE_API(CLOSE_HANDLE, CsrCloseHandle),
CSRSS_DEFINE_API(VERIFY_HANDLE, CsrVerifyHandle),
CSRSS_DEFINE_API(DUPLICATE_HANDLE, CsrDuplicateHandle),
CSRSS_DEFINE_API(GET_INPUT_WAIT_HANDLE, CsrGetInputWaitHandle),
{ 0, 0, NULL }
};
static NTSTATUS STDCALL
CsrpCreateListenPort (IN LPWSTR Name,
IN OUT PHANDLE Port,
IN PTHREAD_START_ROUTINE ListenThread)
{
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES PortAttributes;
UNICODE_STRING PortName;
DPRINT("CSR: %s called\n", __FUNCTION__);
RtlInitUnicodeString (& PortName, Name);
InitializeObjectAttributes (& PortAttributes,
& PortName,
0,
NULL,
NULL);
Status = NtCreatePort ( Port,
& PortAttributes,
LPC_MAX_DATA_LENGTH, /* TODO: make caller set it*/
LPC_MAX_MESSAGE_LENGTH, /* TODO: make caller set it*/
0); /* TODO: make caller set it*/
if(!NT_SUCCESS(Status))
{
DPRINT1("CSR: %s: NtCreatePort failed (Status=%08lx)\n",
__FUNCTION__, Status);
return Status;
}
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
FALSE,
0,
0,
0,
(PTHREAD_START_ROUTINE) ListenThread,
*Port,
NULL,
NULL);
return Status;
}
/* === INIT ROUTINES === */
/**********************************************************************
* CsrpCreateHeap/3
*/
static NTSTATUS
CsrpCreateHeap (int argc, char ** argv, char ** envp)
{
DPRINT("CSR: %s called\n", __FUNCTION__);
CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
NULL,
65536,
65536,
NULL,
NULL);
if (CsrssApiHeap == NULL)
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
/**********************************************************************
* CsrpCreateCallbackPort/3
*/
static NTSTATUS
CsrpCreateCallbackPort (int argc, char ** argv, char ** envp)
{
DPRINT("CSR: %s called\n", __FUNCTION__);
return CsrpCreateListenPort (L"\\Windows\\SbApiPort",
& hSbApiPort,
ServerSbApiPortThread);
}
/**********************************************************************
* CsrpRegisterSubsystem/3
*/
static NTSTATUS
CsrpRegisterSubsystem (int argc, char ** argv, char ** envp)
{
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES BootstrapOkAttributes;
UNICODE_STRING Name;
DPRINT("CSR: %s called\n", __FUNCTION__);
/*
* Create the event object the callback port
* thread will signal *if* the SM will
* authorize us to bootstrap.
*/
RtlInitUnicodeString (& Name, L"\\CsrssBooting");
InitializeObjectAttributes(& BootstrapOkAttributes,
& Name,
0, NULL, NULL);
Status = NtCreateEvent (& hBootstrapOk,
EVENT_ALL_ACCESS,
& BootstrapOkAttributes,
SynchronizationEvent,
FALSE);
if(!NT_SUCCESS(Status))
{
DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n",
__FUNCTION__, Status);
return Status;
}
/*
* Let's tell the SM a new environment
* subsystem server is in the system.
*/
RtlInitUnicodeString (& Name, L"\\Windows\\SbApiPort");
DPRINT("CSR: %s: registering with SM for\n IMAGE_SUBSYSTEM_WINDOWS_CUI == 3\n", __FUNCTION__);
Status = SmConnectApiPort (& Name,
hSbApiPort,
IMAGE_SUBSYSTEM_WINDOWS_CUI,
& hSmApiPort);
if(!NT_SUCCESS(Status))
{
DPRINT("CSR: %s unable to connect to the SM (Status=0x%08lx)\n",
__FUNCTION__, Status);
NtClose (hBootstrapOk);
return Status;
}
/*
* Wait for SM to reply OK... If the SM
* won't answer, we hang here forever!
*/
DPRINT("CSR: %s: waiting for SM to OK boot...\n", __FUNCTION__);
Status = NtWaitForSingleObject (hBootstrapOk,
FALSE,
NULL);
NtClose (hBootstrapOk);
return Status;
}
/**********************************************************************
* EnvpToUnicodeString/2
*/
static ULONG FASTCALL
EnvpToUnicodeString (char ** envp, PUNICODE_STRING UnicodeEnv)
{
ULONG CharCount = 0;
ULONG Index = 0;
ANSI_STRING AnsiEnv;
UnicodeEnv->Buffer = NULL;
for (Index=0; NULL != envp[Index]; Index++)
{
CharCount += strlen (envp[Index]);
++ CharCount;
}
++ CharCount;
AnsiEnv.Buffer = RtlAllocateHeap (RtlGetProcessHeap(), 0, CharCount);
if (NULL != AnsiEnv.Buffer)
{
PCHAR WritePos = AnsiEnv.Buffer;
for (Index=0; NULL != envp[Index]; Index++)
{
strcpy (WritePos, envp[Index]);
WritePos += strlen (envp[Index]) + 1;
}
/* FIXME: the last (double) nullterm should perhaps not be included in Length
* but only in MaximumLength. -Gunnar */
AnsiEnv.Buffer [CharCount-1] = '\0';
AnsiEnv.Length = CharCount;
AnsiEnv.MaximumLength = CharCount;
RtlAnsiStringToUnicodeString (UnicodeEnv, & AnsiEnv, TRUE);
RtlFreeHeap (RtlGetProcessHeap(), 0, AnsiEnv.Buffer);
}
return CharCount;
}
/**********************************************************************
* CsrpLoadKernelModeDriver/3
*/
static NTSTATUS
CsrpLoadKernelModeDriver (int argc, char ** argv, char ** envp)
{
NTSTATUS Status = STATUS_SUCCESS;
WCHAR Data [MAX_PATH + 1];
ULONG DataLength = sizeof Data;
ULONG DataType = 0;
UNICODE_STRING Environment;
DPRINT("SM: %s called\n", __FUNCTION__);
EnvpToUnicodeString (envp, & Environment);
Status = SmLookupSubsystem (L"Kmode",
Data,
& DataLength,
& DataType,
Environment.Buffer);
RtlFreeUnicodeString (& Environment);
if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
{
WCHAR ImagePath [MAX_PATH + 1] = {0};
UNICODE_STRING ModuleName;
wcscpy (ImagePath, L"\\??\\");
wcscat (ImagePath, Data);
RtlInitUnicodeString (& ModuleName, ImagePath);
Status = NtSetSystemInformation(/* FIXME: SystemLoadAndCallImage */
SystemExtendServiceTableInformation,
& ModuleName,
sizeof ModuleName);
if(!NT_SUCCESS(Status))
{
DPRINT("WIN: %s: loading Kmode failed (Status=0x%08lx)\n",
__FUNCTION__, Status);
}
}
return Status;
}
/**********************************************************************
* CsrpCreateApiPort/2
*/
static NTSTATUS
CsrpCreateApiPort (int argc, char ** argv, char ** envp)
{
DPRINT("CSR: %s called\n", __FUNCTION__);
CsrInitProcessData();
return CsrpCreateListenPort(L"\\Windows\\ApiPort", &hApiPort,
(PTHREAD_START_ROUTINE)ClientConnectionThread);
}
/**********************************************************************
* CsrpApiRegisterDef/0
*/
static NTSTATUS
CsrpApiRegisterDef (int argc, char ** argv, char ** envp)
{
return CsrApiRegisterDefinitions(NativeDefinitions);
}
/**********************************************************************
* CsrpCCTS/2
*/
static NTSTATUS
CsrpCCTS (int argc, char ** argv, char ** envp)
{
ULONG Dummy;
ULONG DummyLength = sizeof(Dummy);
return CsrClientConnectToServer(L"\\Windows",
0, &Dummy, &DummyLength, NULL);
}
/**********************************************************************
* CsrpRunWinlogon/0
*
* Start the logon process (winlogon.exe).
*
* TODO: this should be moved in CsrpCreateSession/x (one per session)
* TODO: in its own desktop (one logon desktop per winstation).
*/
static NTSTATUS
CsrpRunWinlogon (int argc, char ** argv, char ** envp)
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING ImagePath;
UNICODE_STRING CommandLine;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
RTL_USER_PROCESS_INFORMATION ProcessInfo;
DPRINT("CSR: %s called\n", __FUNCTION__);
/* initialize the process parameters */
RtlInitUnicodeString (& ImagePath, L"\\SystemRoot\\system32\\winlogon.exe");
RtlInitUnicodeString (& CommandLine, L"");
RtlCreateProcessParameters(& ProcessParameters,
& ImagePath,
NULL,
NULL,
& CommandLine,
NULL,
NULL,
NULL,
NULL,
NULL);
/* Create the winlogon process */
Status = RtlCreateUserProcess (& ImagePath,
OBJ_CASE_INSENSITIVE,
ProcessParameters,
NULL,
NULL,
NULL,
FALSE,
NULL,
NULL,
& ProcessInfo);
/* Cleanup */
RtlDestroyProcessParameters (ProcessParameters);
if (!NT_SUCCESS(Status))
{
DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
__FUNCTION__, Status);
}
ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
return Status;
}
static NTSTATUS
CsrpCreateHardErrorPort (int argc, char ** argv, char ** envp)
{
return NtSetDefaultHardErrorPort(hApiPort);
}
typedef NTSTATUS (* CSR_INIT_ROUTINE)(int,char**,char**);
struct {
BOOL Required;
CSR_INIT_ROUTINE EntryPoint;
PCHAR ErrorMessage;
} InitRoutine [] = {
{TRUE, CsrpCreateCallbackPort, "create the callback port \\Windows\\SbApiPort"},
{TRUE, CsrpRegisterSubsystem, "register with SM"},
{TRUE, CsrpCreateHeap, "create the CSR heap"},
{TRUE, CsrpCreateApiPort, "create the api port \\Windows\\ApiPort"},
{TRUE, CsrpCreateHardErrorPort, "create the hard error port"},
{TRUE, CsrpCreateObjectDirectory,"create the object directory \\Windows"},
{TRUE, CsrpLoadKernelModeDriver, "load Kmode driver"},
{TRUE, CsrpInitVideo, "initialize video"},
{TRUE, CsrpApiRegisterDef, "initialize api definitions"},
{TRUE, CsrpCCTS, "connect client to server"},
{TRUE, CsrpInitWin32Csr, "load usermode dll"},
{TRUE, CsrpRunWinlogon, "run WinLogon"},
};
1999-07-17 23:10:31 +00:00
/**********************************************************************
* NAME
* CsrServerInitialization
1999-07-17 23:10:31 +00:00
*
* DESCRIPTION
* Initialize the Win32 environment subsystem server.
1999-07-17 23:10:31 +00:00
*
* RETURN VALUE
* TRUE: Initialization OK; otherwise FALSE.
*/
BOOL STDCALL
CsrServerInitialization (
int argc,
char ** argv,
char ** envp
)
{
UINT i = 0;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("CSR: %s called\n", __FUNCTION__);
for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++)
{
Status = InitRoutine[i].EntryPoint(argc,argv,envp);
if(!NT_SUCCESS(Status))
{
DPRINT1("CSR: %s: failed to %s (Status=%08lx)\n",
__FUNCTION__,
InitRoutine[i].ErrorMessage,
Status);
if (InitRoutine[i].Required)
{
return FALSE;
}
}
}
if (CallInitComplete())
{
Status = SmCompleteSession (hSmApiPort,hSbApiPort,hApiPort);
return TRUE;
}
return FALSE;
}
/* EOF */