diff options
Diffstat (limited to '')
-rw-r--r-- | private/os2/server/srvinit.c | 736 |
1 files changed, 736 insertions, 0 deletions
diff --git a/private/os2/server/srvinit.c b/private/os2/server/srvinit.c new file mode 100644 index 000000000..a1511a511 --- /dev/null +++ b/private/os2/server/srvinit.c @@ -0,0 +1,736 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + srvinit.c + +Abstract: + + This is the main initialization module for the OS/2 Subsystem Server + +Author: + + Steve Wood (stevewo) 22-Aug-1989 + +Environment: + + User Mode Only + +Revision History: + +--*/ + +#include "os2srv.h" +#include "os2tile.h" +#include "os2win.h" +#include "os2err.h" +#define NTOS2_ONLY +#include "sesport.h" +#include "os2ldr.h" + + +extern HANDLE FirstOs2ProcessHandle; + +BOOLEAN +SetProcessShutdownParameters( + DWORD dwLevel, + DWORD dwFlags + ); + +BOOLEAN +InitializeSecurityDescriptor ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD dwRevision + ); + +BOOLEAN +SetSecurityDescriptorDacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + BOOLEAN bDaclPresent, + PACL pDacl, + BOOLEAN bDaclDefaulted + ); + +BOOLEAN +SetKernelObjectSecurity ( + HANDLE Handle, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +WCHAR Os2SystemDirectory[MAX_PATH]; +ULONG Os2GlobalInfoSeg; +HANDLE Os2GlobalInfoSegHandle; +HANDLE UpDateInfoSegThreadHandle; +HANDLE Os2SyncSem; + + +APIRET +Os2GetSysInfo(VOID) +{ + APIRET RetCode; + GINFOSEG *pGlobalInfo; + TIME_FIELDS NtDateTime; + LARGE_INTEGER nttime, LocalTime; + SYSTEM_TIMEOFDAY_INFORMATION SystemInformation; + ULONG utemp = 0xFFFFFFFF/10000; + SHORT TimeZone; + + pGlobalInfo = (GINFOSEG *) Os2GlobalInfoSeg; + + // + // fill in global info fields + // + + RetCode = Or2GetDateTimeInfo( + &nttime, + &LocalTime, + &NtDateTime, + (PVOID)&SystemInformation, + &TimeZone + ); + + if (RetCode) + { +#if DBG + IF_OS2_DEBUG( MISC ) + { + KdPrint(( "Os2GetSysInfo: Error at Or2GetDateTimeInfo %lu\n", + RetCode)); + } +#endif + return (RetCode); + } + + pGlobalInfo->year = NtDateTime.Year; + pGlobalInfo->month = (UCHAR)(NtDateTime.Month); + pGlobalInfo->day = (UCHAR)(NtDateTime.Day); + pGlobalInfo->weekday = (UCHAR)(NtDateTime.Weekday); + pGlobalInfo->hour = (UCHAR)(NtDateTime.Hour); + pGlobalInfo->minutes = (UCHAR)(NtDateTime.Minute); + pGlobalInfo->seconds = (UCHAR)(NtDateTime.Second); + pGlobalInfo->hundredths = (UCHAR)(NtDateTime.Milliseconds / 10); + pGlobalInfo->weekday = (UCHAR)NtDateTime.Weekday; + pGlobalInfo->timezone = TimeZone; + + RtlTimeToSecondsSince1970 ( &LocalTime, &(pGlobalInfo->time) ); + + // + // Convert UTC to Local time: no need beacuse the subtract between 2 UTCs + // + + SystemInformation.BootTime = RtlLargeIntegerSubtract(nttime, + SystemInformation.BootTime); + pGlobalInfo->msecs = SystemInformation.BootTime.LowPart/10000 + + ((ULONG)SystemInformation.BootTime.HighPart)*utemp; + + return(0); +} + + +VOID +UpdateInfoSegThread( + ULONG param + ) +{ + APIRET rc; + NTSTATUS Status; + LARGE_INTEGER DelayInterval; + + UNREFERENCED_PARAMETER(param); + + +#if DBG + IF_OS2_DEBUG( MISC ) { + KdPrint(("Entering UpdateInfoSeg.\n")); + } +#endif + + DelayInterval = RtlEnlargedIntegerMultiply( 10, -10000 ); + for (;;) { + rc = Os2GetSysInfo(); + if (rc) { +#if DBG + KdPrint(("UpdateInfoSegThread: error at Os2GetSysInfo %d\n", rc)); +#endif + ASSERT (FALSE); + NtTerminateThread(UpDateInfoSegThreadHandle, rc); + } + Status = NtDelayExecution( TRUE, &DelayInterval ); + DelayInterval = RtlEnlargedIntegerMultiply( 10, -10000 ); + } +} + + +NTSTATUS +Os2InitializeGlobalInfoSeg( VOID ) +{ + + NTSTATUS Status; + ULONG AllocationAttributes; + LARGE_INTEGER SectionSize; + ULONG RegionSize = 0; + GINFOSEG *pGlobalInfoSeg; + CLIENT_ID ClientId; + + AllocationAttributes = SEC_COMMIT; + SectionSize.LowPart = sizeof(GINFOSEG); + SectionSize.HighPart = 0; + Status = NtCreateSection( &Os2GlobalInfoSegHandle, + SECTION_ALL_ACCESS, + NULL, + &SectionSize, + PAGE_READWRITE, + AllocationAttributes, + NULL + ); + + if (!NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: unable to create the GINFOSEG section, Status=%x\n", Status)); +#endif + return( Status ); + } + + Os2GlobalInfoSeg = GINFOSEG_BASE; + Status = NtMapViewOfSection( Os2GlobalInfoSegHandle, + NtCurrentProcess(), + (PVOID) &Os2GlobalInfoSeg, + 0, + 0, + NULL, + &RegionSize, + ViewUnmap, + 0, + PAGE_READWRITE + ); + + if (!NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: unable to Map View of the GINFOSEG section, Status=%x\n", Status)); +#endif + return( Status ); + } + + pGlobalInfoSeg = (GINFOSEG *) Os2GlobalInfoSeg; + +// pGlobalInfoSeg->pidForeground = (USHORT)(Od2Process->Pib.ProcessId); +// pGlobalInfoSeg->sgCurrent = (UCHAR)Od2SessionNumber; + + // + // Set Fixed Global Information Fields + // + pGlobalInfoSeg->uchMajorVersion = 10; + pGlobalInfoSeg->uchMinorVersion = 21; + pGlobalInfoSeg->cHugeShift = 3; + + pGlobalInfoSeg->fProtectModeOnly = 1; + + // + // GINFOSEG fields that are set arbitrarily or not + // set at all for now + // + pGlobalInfoSeg->chRevisionLetter = 0; +// pGlobalInfoSeg->sgCurrent = 0; + pGlobalInfoSeg->sgMax = 16; + pGlobalInfoSeg->fDynamicSched = 1; + pGlobalInfoSeg->csecMaxWait = (UCHAR)-1; + pGlobalInfoSeg->cmsecMinSlice = 100; + pGlobalInfoSeg->cmsecMaxSlice = 100; + pGlobalInfoSeg->timezone = (USHORT)(-1); +// pGlobalInfoSeg->amecRAS +// pGlobalInfoSeg->WindowableVioMax +// pGlobalInfoSeg->csgPMMax +#ifdef PMNT +// probably this PMNT can be removed because this is th +// value of global info seg field in OS2 (LiorM) + pGlobalInfoSeg->csgWindowableVioMax = 16; + pGlobalInfoSeg->csgPMMax = 16; +#endif + + pGlobalInfoSeg->bootdrive = (USHORT)Os2BootDrive + 1; + + // + // Get timer resolution + // + + { + SYSTEM_BASIC_INFORMATION sysinfo; + + Status = NtQuerySystemInformation( + SystemBasicInformation, + &sysinfo, + sizeof(sysinfo), + NULL); + + if (!NT_SUCCESS(Status)) { +#if DBG + IF_OS2_DEBUG( MISC ) { + KdPrint(("OS2SRV: unable to query system timer resolution, Status = %lx\n", Status)); + } +#endif + pGlobalInfoSeg->cusecTimerInterval = 310; // default value, comes from OS/2 + } else { + pGlobalInfoSeg->cusecTimerInterval = (USHORT) (sysinfo.TimerResolution / 1000L); + } + } + + Status = RtlCreateUserThread( NtCurrentProcess(), + NULL, + TRUE, + 0, + 0x10000, + 0, // Default to one page + (PUSER_THREAD_START_ROUTINE)UpdateInfoSegThread, + 0, // param + &UpDateInfoSegThreadHandle, + &ClientId + ); + if(!NT_SUCCESS(Status)){ +#if DBG + KdPrint(("Os2InitializeGlobalInfoSeg: can't Create update thread %lx\n", Status)); +#endif + return Status; + } + + Status = NtResumeThread( UpDateInfoSegThreadHandle, NULL ); + if(!NT_SUCCESS(Status)){ +#if DBG + KdPrint(("Os2InitializeGlobalInfoSeg: can't Resume update thread %lx\n", Status)); +#endif + return Status; + } + + return STATUS_SUCCESS; + +} + +NTSTATUS Os2InitializeSyncSem() +{ + NTSTATUS Status; + UNICODE_STRING SemString_U; + OBJECT_ATTRIBUTES Obja; + CHAR sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; + PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)&sd; + + InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(psd, TRUE, NULL, FALSE); // NULL DACL means access free to all + + RtlInitUnicodeString( &SemString_U, OS2_SS_SYNCHRONIZATION_SEM); + InitializeObjectAttributes( + &Obja, + &SemString_U, + OBJ_CASE_INSENSITIVE, + NULL, + psd); + + // + // Create the global subsystem synchronization Nt semaphore + // + Status = NtCreateMutant(&Os2SyncSem, + MUTANT_ALL_ACCESS, + &Obja, + FALSE); + + if (!NT_SUCCESS(Status)) { +#if DBG + IF_OD2_DEBUG ( SEMAPHORES ) { + DbgPrint("Os2InitSyncSem: error at NtCreateSemaphore, Status %x\n", Status); + } +#endif + } + return(Status); +} + +#if PMNT +NTSTATUS Os2InitializePMShellEvent() +{ + NTSTATUS Status; + UNICODE_STRING EventString_U; + OBJECT_ATTRIBUTES Obja; + HANDLE hPMShellEvent; + CHAR sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; + PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)&sd; + + InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(psd, TRUE, NULL, FALSE); // NULL DACL means access free to all + + RtlInitUnicodeString( &EventString_U, OS2_SS_PMSHELL_EVENT); + InitializeObjectAttributes( + &Obja, + &EventString_U, + OBJ_CASE_INSENSITIVE, + NULL, + psd); + + // + // Create the global subsystem PMShell synchronization Nt event + // (create in the unsignalled state - when PMShell comes up, it will + // signal it) + // + Status = NtCreateEvent(&hPMShellEvent, + EVENT_ALL_ACCESS, + &Obja, + NotificationEvent, + FALSE); + + if (!NT_SUCCESS(Status)) + { +#if DBG + DbgPrint("Os2InitializePMShellEvent: error at NtCreateEvent, Status %x\n", Status); +#endif + } + return(Status); +} +#endif // PMNT + +NTSTATUS +Os2Initialize( VOID ) +{ + NTSTATUS Status; + APIRET Rc; + CHAR sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; + PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)&sd; + +#if DBG + if (fService) + KdPrint(("Started OS2SRV init (as a service)\n")); + else + KdPrint(("Started OS2SRV init\n")); +#endif + + // + // We have just created os2srv - set it's security so all clients + // can open it regardless of logon + // + + InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(psd, TRUE, NULL, FALSE); // NULL DACL means access free to all + SetKernelObjectSecurity(GetCurrentProcess(), DACL_SECURITY_INFORMATION, psd); + + SetEventHandlersAndErrorMode(TRUE); + + // + // Create a heap for the OS/2 Server to use for dynamic memory allocation. + // + + Os2Heap = RtlCreateHeap( HEAP_GROWABLE, + NULL, + 64 * 1024, // Initial size of heap is 64K + 4 * 1024, + 0, + NULL // reserved + ); + if (Os2Heap == NULL) { +#if DBG + KdPrint(("OS2SRV: Error at RtlCreateHeap of Os2Heap\n")); + ASSERT(FALSE); +#endif + return STATUS_NO_MEMORY; + } + + // + // Initialize the Process List + // + + Status = Os2InitializeProcessStructure(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize process structure, Status = %X\n", Status)); + ASSERT(FALSE); +#endif + } + + // + // Initialize the Object Manager + // + + Status = Os2InitializeLocalObjectManager(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize local object manager, Status = %X\n", Status)); + ASSERT(FALSE); +#endif + } + + // + // Initialize the Memory Management + // + + Status = Os2InitializeMemory(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize shared memory, Status = %X\n", Status)); + ASSERT(FALSE); +#endif + } + + // + // Initialize the Semaphore Table + // + + Status = Os2InitializeSemaphores(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize semaphores, Status = %X\n", Status)); + ASSERT(FALSE); +#endif + } + + // + // Initialize the Queue Table + // + + Status = Os2InitializeQueues(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize queues, Status = %X\n", Status)); + ASSERT(FALSE); +#endif + } + + // + // Initialize the Name Space + // + + Status = Os2InitializeNameSpace(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize name space, Status = %X\n", Status)); +#endif + ExitProcess(1); + } + + Status = Os2InitializeSyncSem(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Status %lx from Os2InitializeSyncSem\n", Status)); + ASSERT(FALSE); +#endif + return Status; + } + +#if PMNT + Status = Os2InitializePMShellEvent(); + if (! NT_SUCCESS( Status )) + { +#if DBG + KdPrint(("OS2SRV: Status %lx from Os2InitializePMShellSem\n", Status)); + ASSERT(FALSE); +#endif + return Status; + } +#endif // PMNT + + // Make it so that OS2SRV gets the shutdown/logoff message last. Default + // is 0x280, minimum range for app is 0x100 + if (!SetProcessShutdownParameters( + 0x27e, // Just below the priority of PMShell + 0)) + { +#if DBG + DbgPrint("Os2srv: SetProcessShutdownParameters failed !\n"); +#endif + } + + // + // Initialize the registry + // + + if (GetSystemDirectoryW(Os2SystemDirectory, MAX_PATH) == 0) { +#if DBG + KdPrint(("OS2SRV: Cannot obtain name of system directory\n")); + ASSERT(FALSE); +#endif + return(STATUS_UNSUCCESSFUL); + } + + Status = Os2InitializeRegistry(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize registry, Status = %X\n", Status)); +#endif + } + + // + // Initialize the NLS + // + + if( Rc = Os2InitializeNLS() ) + { +#if DBG + KdPrint(("OS2SRV: Cannot initialize NLS, Rc = %d\n", Rc )); + ASSERT(FALSE); +#endif + } + + // + // Initialize the loader + // + if (!ldrInit()) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize Loader\n")); + ASSERT(FALSE); +#endif + } + + // + // Initialize the Global info seg + // + + if( Status = Os2InitializeGlobalInfoSeg() ) + { +#if DBG + KdPrint(("OS2SRV: Cannot initialize Global Info, Status = %d\n", Status )); + ASSERT(FALSE); +#endif + } + + // + // Initialize the OS2 Server Console Session Port, the listen thread and one + // request threads. + // + + Status = Os2InitializeConsolePort(); + + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize Console Port, Status = %X\n", Status )); + ASSERT(FALSE); +#endif + return Status; + } + + // + // Initialize the OS2 Server API Port, the listen thread and one or more + // request threads. + // + + Status = Os2DebugPortInitialize(); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Cannot initialize Debug Port, Status = %X\n", Status )); + ASSERT(FALSE); +#endif + return Status; + } + + Status = DbgSsInitialize(Os2SessionPort, Os2UiLookup, NULL, NULL); + if (! NT_SUCCESS( Status )) { +#if DBG + KdPrint(("OS2SRV: Status %lx from DbgSsInitialize\n", Status)); + ASSERT(FALSE); +#endif + return Status; + } + + if (! NT_SUCCESS(Os2GetClientId())) { +#if DBG + KdPrint(("OS2SRV: Can not debug\n")); +#endif + } + + + return( Status ); +} + + +ULONG +NtGetIntegerFromUnicodeString(IN WCHAR *WString) +{ + ULONG Code = 0; + NTSTATUS Status; + UNICODE_STRING UnicodeString; + + RtlInitUnicodeString( + &UnicodeString, + WString); + + Status = RtlUnicodeStringToInteger( + &UnicodeString, + 10, + &Code); + +#if DBG + if (! NT_SUCCESS( Status )) + { + IF_OS2_DEBUG( NLS ) + { + KdPrint(("InitNLS: RtlUnicodeStringToInteger failed, Status %lu\n", + Status )); + } + } +#endif + return(Code); +} + + +BOOLEAN +Os2SrvHandleCtrlEvent( + IN int CtrlType + ) +{ + BOOLEAN Wait = FALSE/*, Rc*/; + OS2SESREQUESTMSG RequestMsg; + ULONG i; + LARGE_INTEGER DelayInterval; + +#if DBG + IF_OS2_DEBUG( SIG ) + { + KdPrint(("OS2SRV(EventHandlerRoutine): Ctr-Type %u\n", CtrlType)); + } +#endif + + Os2AcquireStructureLock(); + for ( i = 1 ; ( i < OS2_MAX_SESSION ) ; i++ ) + { + if ( SessionTable[i].Session != NULL ) + { + RequestMsg.Session = SessionTable[i].Session; + RequestMsg.d.Signal.Type = CtrlType; + Os2CtrlSignalHandler(&RequestMsg, NULL); + Wait = TRUE; + } + } + Os2ReleaseStructureLock(); + + while (Wait) + { +#if DBG + KdPrint(("OS2SRV(EventHandlerRoutine): Waiting 2 seconds for all sessions to clear\n")); +#endif + DelayInterval = RtlEnlargedIntegerMultiply( 2000, -10000 ); + NtDelayExecution( (BOOLEAN)TRUE, &DelayInterval ); + Wait = FALSE; + + for ( i = 1 ; ( i < OS2_MAX_SESSION ) ; i++ ) + { + if ( SessionTable[i].Session != NULL ) + { + Wait = TRUE; + } + } + + } + // + // Wait for the first application that created the server - + // The logoff/shutdown logic is LIFO, so we want to prevent + // os2srv from exiting if that app is not gone yet, otherwise + // the kernel hangs because of debug port handshake + // + if ( FirstOs2ProcessHandle != 0 && FirstOs2ProcessHandle != (HANDLE)-1 ) { + NtWaitForSingleObject( + FirstOs2ProcessHandle, + TRUE, // Alertable + NULL + ); + } + // + // Now we can exit the server + // + Os2SrvExitProcess(0); + return(TRUE); +} |