summaryrefslogtreecommitdiffstats
path: root/private/os2/server/srvinit.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/os2/server/srvinit.c736
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);
+}